nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * --------------------------------------- 00024 */ 00025 00094 #ifdef HAVE_CONFIG_H 00095 #include "config.h" 00096 #endif 00097 00098 #ifdef _SOLARIS 00099 #include "solaris_port.h" 00100 #endif 00101 00102 #include "shell.h" 00103 #include "shell_utils.h" 00104 #include "shell_vars.h" 00105 #include "log.h" 00106 #include "commands.h" 00107 #include "cmd_tools.h" 00108 00109 #include "abstract_mem.h" 00110 #include <unistd.h> 00111 #include <string.h> 00112 00113 #include <stdio.h> 00114 #include <pthread.h> 00115 00116 #ifdef HAVE_LIBREADLINE 00117 #include <readline/readline.h> 00118 #include <readline/history.h> 00119 #endif 00120 00121 #include <sys/time.h> 00122 #include "shell.h" 00123 00124 #define MAX_OUTPUT_LEN (1024*1024) /* 1MB */ 00125 00126 #define TRACEBUFFSIZE 1024 00127 00128 #define PROMPTSIZE 64 00129 00130 layer_def_t layer_list[] = { 00131 {"FSAL", commands_FSAL, "File system abstraction layer", fsal_layer_SetLogLevel} 00132 , 00133 {"Cache_inode", commands_Cache_inode, "Cache inode layer", Cache_inode_layer_SetLogLevel} 00134 , 00135 {"NFS", commands_NFS, 00136 "NFSv2, NFSv3, MNTv1, MNTv3 protocols (direct calls, not through RPCs)", 00137 nfs_layer_SetLogLevel} 00138 , 00139 {"NFS_remote", commands_NFS_remote, 00140 "NFSv2, NFSv3, MNTv1, MNTv3 protocols (calls through RPCs)", 00141 nfs_remote_layer_SetLogLevel} 00142 , 00143 {NULL, NULL, NULL, NULL} /* End of layer list */ 00144 }; 00145 00146 char *shell_special_vars[] = { 00147 "INPUT", /* a filename or <stdin> */ 00148 "INTERACTIVE", /* Indicates if we are in interactive mode */ 00149 "LAYER", /* The current layer */ 00150 "STATUS", /* Last command status */ 00151 "?", /* idem */ 00152 "VERBOSE", /* shel verbose mode */ 00153 "DEBUG_LEVEL", /* layer debug level */ 00154 "DBG_LVL", /* idem */ 00155 "PROMPT", /* shell prompt string */ 00156 "LINE", /* line number */ 00157 00158 /* end of special vars list */ 00159 NULL 00160 }; 00161 00162 command_def_t shell_utils[] = { 00163 {"chomp", util_chomp, "removes final newline character"}, 00164 {"cmp", util_cmp, "compares two expressions"}, 00165 {"diff", util_diff, "lists differences between two expressions"}, 00166 {"eq", util_cmp, "test if two expressions are equal"}, 00167 {"meminfo", util_meminfo, "prints information about memory use"}, 00168 {"ne", util_cmp, "test if two expressions are different"}, 00169 {"shell", util_shell, "executes a real shell command"}, 00170 {"sleep", util_sleep, "suspends script execution for some time"}, 00171 {"timer", util_timer, "timer management command"}, 00172 {"wc", util_wc, "counts the number of char/words/lines in a string"}, 00173 00174 {NULL, NULL, NULL} /* End of command list */ 00175 }; 00176 00177 /* ------------------------------------------* 00178 * Barrier management. 00179 * ------------------------------------------*/ 00180 00181 #define P_shell( _mutex_ ) pthread_mutex_lock( &_mutex_ ) 00182 #define V_shell( _mutex_ ) pthread_mutex_unlock( &_mutex_ ) 00183 00184 /* variables for managing barriers */ 00185 00186 /* barrier protection */ 00187 static pthread_mutex_t barrier_mutex = PTHREAD_MUTEX_INITIALIZER; 00188 00189 /* condition for crossing barrier */ 00190 static pthread_cond_t barrier_cond = PTHREAD_COND_INITIALIZER; 00191 00192 /* total number of threads to wait for */ 00193 static int total_nb_threads = -1; /* -1 = not initialized */ 00194 00195 /* number of threads that reached the barrier */ 00196 static int nb_waiting_threads = 0; 00197 00202 int shell_BarrierInit(int nb_threads) 00203 { 00204 00205 P_shell(barrier_mutex); 00206 00207 if(total_nb_threads == -1) 00208 { 00209 total_nb_threads = nb_threads; 00210 V_shell(barrier_mutex); 00211 return SHELL_SUCCESS; 00212 } 00213 else 00214 { 00215 V_shell(barrier_mutex); 00216 printf("ganeshell: Error: Barrier already initialized\n"); 00217 return SHELL_ERROR; 00218 } 00219 } 00220 00221 static int shell_BarrierWait() 00222 { 00223 00224 P_shell(barrier_mutex); 00225 00226 /* not used in a single thread environment */ 00227 00228 if(total_nb_threads == -1) 00229 { 00230 V_shell(barrier_mutex); 00231 return SHELL_ERROR; 00232 } 00233 00234 /* increase number of waiting threads */ 00235 00236 nb_waiting_threads++; 00237 00238 /* test for condition */ 00239 00240 if(nb_waiting_threads == total_nb_threads) 00241 { 00242 /* reset the number of waiting threads */ 00243 nb_waiting_threads = 0; 00244 00245 /* wake up all threads */ 00246 pthread_cond_broadcast(&barrier_cond); 00247 00248 } 00249 else 00250 pthread_cond_wait(&barrier_cond, &barrier_mutex); 00251 00252 /* leaves the critical section */ 00253 00254 V_shell(barrier_mutex); 00255 00256 return SHELL_SUCCESS; 00257 00258 } 00259 00260 /* ------------------------------------------* 00261 * Thread safety management. 00262 * ------------------------------------------*/ 00263 00264 /* threads keys */ 00265 static pthread_key_t thread_key; 00266 static pthread_once_t once_key = PTHREAD_ONCE_INIT; 00267 00268 /* init pthtread_key for current thread */ 00269 00270 static void init_keys(void) 00271 { 00272 if(pthread_key_create(&thread_key, NULL) == -1) 00273 printf("Error %d creating pthread key for thread %p : %s\n", 00274 errno, (caddr_t) pthread_self(), strerror(errno)); 00275 00276 return; 00277 } /* init_keys */ 00278 00283 static shell_state_t *GetShellContext() 00284 { 00285 00286 shell_state_t *p_current_thread_vars; 00287 00288 /* first, we init the keys if this is the first time */ 00289 if(pthread_once(&once_key, init_keys) != 0) 00290 { 00291 printf("Error %d calling pthread_once for thread %p : %s\n", 00292 errno, (caddr_t) pthread_self(), strerror(errno)); 00293 return NULL; 00294 } 00295 00296 p_current_thread_vars = (shell_state_t *) pthread_getspecific(thread_key); 00297 00298 /* we allocate the thread context if this is the first time */ 00299 if(p_current_thread_vars == NULL) 00300 { 00301 00302 /* allocates thread structure */ 00303 p_current_thread_vars = gsh_malloc(sizeof(shell_state_t)); 00304 00305 /* panic !!! */ 00306 if(p_current_thread_vars == NULL) 00307 { 00308 printf("%p:ganeshell: Not enough memory\n", (caddr_t) pthread_self()); 00309 return NULL; 00310 } 00311 00312 /* Clean thread context */ 00313 00314 memset(p_current_thread_vars, 0, sizeof(shell_state_t)); 00315 00316 /* setting default values */ 00317 00318 p_current_thread_vars->input_stream = stdin; 00319 p_current_thread_vars->interactive = TRUE; 00320 p_current_thread_vars->layer = NULL; 00321 p_current_thread_vars->status = 0; 00322 p_current_thread_vars->verbose = 0; 00323 p_current_thread_vars->debug_level = NIV_EVENT; 00324 p_current_thread_vars->line = 0; 00325 00326 /* set the specific value */ 00327 pthread_setspecific(thread_key, (void *)p_current_thread_vars); 00328 00329 } 00330 00331 return p_current_thread_vars; 00332 00333 } /* GetShellContext */ 00334 00335 /*------------------------------------------------------------------ 00336 * Main shell routines. 00337 *-----------------------------------------------------------------*/ 00338 00344 int shell_Init(int verbose, char *input_file, char *prompt, int shell_index) 00345 { 00346 00347 int rc; 00348 char localmachine[256]; 00349 shell_state_t *context; 00350 00351 /* Init logging */ 00352 00353 SetNamePgm("ganeshell"); 00354 /*if (verbose) */ 00355 SetDefaultLogging("STDERR"); 00356 /*else 00357 SetDefaultLogging( "/dev/null" ) ; */ 00358 00359 SetNameFunction("shell"); 00360 00361 /* getting the hostname */ 00362 if(gethostname(localmachine, sizeof(localmachine)) != 0) 00363 { 00364 fprintf(stderr, "Error %d calling gethostname.\n", errno); 00365 return errno; 00366 } 00367 else 00368 SetNameHost(localmachine); 00369 00370 InitLogging(); 00371 00372 /* retrieve/initialize shell context */ 00373 00374 context = GetShellContext(); 00375 00376 /* Initializes verbose mode. */ 00377 00378 if((rc = shell_SetVerbose(context, (verbose ? "1" : "0")))) 00379 return rc; 00380 00381 if((rc = shell_SetDbgLvl(context, "NIV_EVENT"))) 00382 return rc; 00383 00384 /* Then, initializes input file. */ 00385 00386 if((rc = shell_SetInput(context, input_file))) 00387 return rc; 00388 00389 /* Initialize prompt */ 00390 00391 if((rc = shell_SetPrompt(context, prompt))) 00392 return rc; 00393 00394 /* Initialize Shell id */ 00395 00396 if((rc = shell_SetShellId(context, shell_index))) 00397 return rc; 00398 00399 return SHELL_SUCCESS; 00400 00401 } 00402 00403 /* reads a line from input, and prints a prompt in interactive mode. */ 00404 00405 00406 #ifdef HAVE_LIBREADLINE 00407 /* the same as previous, except it doesnt not trunc line at # sign */ 00408 00409 static char *skipblanks2(char *str) 00410 { 00411 00412 char *curr = str; 00413 00414 while(1) 00415 { 00416 00417 switch (*curr) 00418 { 00419 /* end of lines */ 00420 case '\0': 00421 return NULL; 00422 00423 case ' ': 00424 case '\t': 00425 case '\r': 00426 case '\n': 00427 curr++; 00428 break; 00429 00430 default: 00431 return curr; 00432 00433 } /* switch */ 00434 00435 } /* while */ 00436 00437 } /* skipblanks2 */ 00438 00439 00440 #endif 00441 00442 static char *shell_readline(shell_state_t * context, char *s, int n, FILE * stream, 00443 int interactive) 00444 { 00445 00446 char *retval = shell_GetPrompt(context); 00447 00448 #ifdef HAVE_LIBREADLINE 00449 00450 char *l; 00451 00452 if(interactive) 00453 { 00454 /* use readline */ 00455 l = readline((retval ? retval : "")); 00456 if(l) 00457 { 00458 strncpy(s, l, n); 00459 00460 /* add line to history, if it is not empty */ 00461 l = skipblanks2(l); 00462 00463 if(l != NULL) 00464 add_history(l); 00465 00466 return s; 00467 } 00468 else 00469 return NULL; 00470 } 00471 else 00472 return fgets(s, n, stream); 00473 00474 #else 00475 if(interactive) 00476 printf("%s", (retval ? retval : "")); 00477 00478 return fgets(s, n, stream); 00479 #endif 00480 00481 } 00482 00486 int shell_Launch() 00487 { 00488 00489 char cmdline[MAX_LINE_LEN + 1]; 00490 char *arglist[MAX_ARGS]; 00491 int alloctab[MAX_ARGS]; 00492 int argcount; 00493 int rc = 0; 00494 00495 shell_state_t *context = GetShellContext(); 00496 00497 while(shell_readline(context, cmdline, MAX_LINE_LEN, 00498 context->input_stream, context->interactive) != NULL) 00499 { 00500 00501 /* Increments line number */ 00502 00503 shell_SetLine(context, shell_GetLine(context) + 1); 00504 00505 /* Parse command line */ 00506 00507 if(shell_ParseLine(cmdline, arglist, &argcount)) 00508 continue; 00509 00510 /* nothing to do if the line is empty. */ 00511 if(argcount == 0) 00512 continue; 00513 00514 /* Evaluates arguments */ 00515 00516 if(shell_SolveArgs(argcount, arglist, alloctab)) 00517 continue; 00518 00519 /* Execute command */ 00520 rc = shell_Execute(argcount, arglist, stdout); 00521 00522 /* clean allocated strings */ 00523 shell_CleanArgs(argcount, arglist, alloctab); 00524 00525 /* set command status */ 00526 shell_SetStatus(context, rc); 00527 00528 } 00529 return rc; 00530 } 00531 00532 /*------------------------------------------------------------------ 00533 * Parsing and execution routines. 00534 *-----------------------------------------------------------------*/ 00535 00536 /* address of the first non blank char if any, null else.*/ 00537 00538 static char *skipblanks(char *str) 00539 { 00540 00541 char *curr = str; 00542 00543 while(1) 00544 { 00545 00546 switch (*curr) 00547 { 00548 /* end of lines */ 00549 case '\0': 00550 case '#': 00551 return NULL; 00552 00553 case ' ': 00554 case '\t': 00555 case '\r': 00556 case '\n': 00557 curr++; 00558 break; 00559 00560 default: 00561 return curr; 00562 00563 } /* switch */ 00564 00565 } /* while */ 00566 00567 } /* skipblanks */ 00568 00569 /* adress of the first blank char 00570 * outside a string. 00571 */ 00572 static char *nextblank(char *str) 00573 { 00574 00575 int dquote_string = 0; 00576 int squote_string = 0; 00577 int bquote_string = 0; 00578 00579 int escaped = 0; 00580 00581 char *curr = str; 00582 00583 while(1) 00584 { 00585 00586 switch (*curr) 00587 { 00588 00589 /* end of lines */ 00590 case ' ': 00591 case '\t': 00592 if(!dquote_string && !squote_string && !bquote_string) 00593 return curr; 00594 else 00595 curr++; 00596 break; 00597 00598 case '\0': 00599 case '\n': 00600 return curr; 00601 break; 00602 00603 case '\\': 00604 /* escape sequence */ 00605 escaped = 1; 00606 curr++; 00607 break; 00608 00609 case '"': 00610 /* start or end of double quoted string */ 00611 if(dquote_string) 00612 dquote_string = 0; 00613 else 00614 (dquote_string) = 1; 00615 curr++; 00616 break; 00617 00618 case '\'': 00619 /* start or end of single quoted string */ 00620 if(squote_string) 00621 squote_string = 0; 00622 else 00623 (squote_string) = 1; 00624 curr++; 00625 break; 00626 00627 case '`': 00628 /* start or end of back-quoted string */ 00629 if(bquote_string) 00630 bquote_string = 0; 00631 else 00632 (bquote_string) = 1; 00633 curr++; 00634 break; 00635 00636 default: 00637 curr++; 00638 00639 } /* switch */ 00640 00641 /* escape ? */ 00642 00643 if(escaped && (*curr != '\0')) 00644 { 00645 escaped = 0; 00646 curr++; 00647 } 00648 00649 } /* while */ 00650 00651 } /* nextblank */ 00652 00664 int shell_ParseLine(char *in_out_line, char **out_arglist, int *p_argcount) 00665 { 00666 00667 char *curr_pos = in_out_line; 00668 (*p_argcount) = 0; 00669 00670 /* While there is something after the Oblivion... */ 00671 00672 while((curr_pos = skipblanks(curr_pos))) 00673 { 00674 out_arglist[(*p_argcount)] = curr_pos; 00675 (*p_argcount)++; 00676 curr_pos = nextblank(curr_pos); 00677 00678 if(*curr_pos == '\0') 00679 break; 00680 else 00681 *curr_pos = '\0'; 00682 00683 curr_pos++; 00684 } 00685 00686 return SHELL_SUCCESS; 00687 00688 } /* shell_ParseLine */ 00689 00695 static int unescape(char *str) 00696 { 00697 00698 char *src = str; 00699 char *tgt = str; 00700 00701 while(*src != '\0') 00702 { 00703 if(*src == '\\') 00704 { 00705 src++; 00706 00707 /* escaped null char */ 00708 if(*src == '\0') 00709 { 00710 #ifdef _DEBUG_SHELL 00711 printf("UNESCAPE ERROR >>>>>>>>>> [%s][%c][%c]\n", str, *src, *tgt); 00712 #endif 00713 return SHELL_ERROR; 00714 } 00715 00716 } 00717 00718 if(tgt != src) 00719 *tgt = *src; 00720 00721 src++; 00722 tgt++; 00723 } 00724 00725 /* final zero */ 00726 if(tgt != src) 00727 *tgt = *src; 00728 00729 return SHELL_SUCCESS; 00730 00731 } 00732 00738 static int remove_quotes(char quote, char **pstr) 00739 { 00740 00741 size_t len = strlen(*pstr); 00742 00743 if(len <= 1) 00744 return SHELL_ERROR; 00745 if((*pstr)[len - 1] != quote) 00746 return SHELL_ERROR; 00747 00748 (*pstr)[len - 1] = '\0'; 00749 (*pstr)[0] = '\0'; 00750 00751 (*pstr)++; 00752 00753 return SHELL_SUCCESS; 00754 00755 } 00756 00768 int shell_SolveArgs(int argc, char **in_out_argv, int *out_allocated) 00769 { 00770 00771 int i; 00772 int error = 0; 00773 char tracebuff[TRACEBUFFSIZE]; 00774 00775 shell_state_t *context = GetShellContext(); 00776 00777 #ifdef _DEBUG_SHELL 00778 printf("SOLVE:"); 00779 for(i = 0; i < argc; i++) 00780 printf("[%s]", in_out_argv[i]); 00781 printf("\n"); 00782 #endif 00783 00784 for(i = 0; i < argc; i++) 00785 { 00786 00787 out_allocated[i] = FALSE; 00788 00789 /* double quotes */ 00790 00791 if(in_out_argv[i][0] == '"') 00792 { 00793 00794 if(remove_quotes('"', &(in_out_argv[i]))) 00795 { 00796 shell_PrintError(context, "Syntax error: Missing closing quotes"); 00797 error = SHELL_SYNTAX_ERROR; 00798 break; 00799 } 00800 00801 if(unescape(in_out_argv[i])) 00802 { 00803 shell_PrintError(context, "Syntax error: Invalid escape sequence"); 00804 error = SHELL_SYNTAX_ERROR; 00805 break; 00806 } 00807 00808 } 00809 00810 /* single quotes */ 00811 00812 else if(in_out_argv[i][0] == '\'') 00813 { 00814 00815 if(remove_quotes('\'', &(in_out_argv[i]))) 00816 { 00817 shell_PrintError(context, "Syntax error: Missing closing quote"); 00818 error = SHELL_SYNTAX_ERROR; 00819 break; 00820 } 00821 00822 if(unescape(in_out_argv[i])) 00823 { 00824 shell_PrintError(context, "Syntax error: Invalid escape sequence"); 00825 error = SHELL_SYNTAX_ERROR; 00826 break; 00827 } 00828 00829 } 00830 00831 /* var name */ 00832 00833 else if(in_out_argv[i][0] == '$') 00834 { 00835 00836 char *value = get_var_value(&(in_out_argv[i][1])); 00837 00838 if(value) 00839 in_out_argv[i] = value; 00840 else 00841 { 00842 snprintf(tracebuff, TRACEBUFFSIZE, 00843 "Undefined variable \"%s\"", &(in_out_argv[i][1])); 00844 shell_PrintError(context, tracebuff); 00845 error = SHELL_NOT_FOUND; 00846 break; 00847 } 00848 00849 } 00850 00851 /* command */ 00852 00853 else if(in_out_argv[i][0] == '`') 00854 { 00855 00856 char *arglist[MAX_ARGS]; 00857 int argcount; 00858 int rc, status; 00859 00860 /* remove quotes */ 00861 00862 if(remove_quotes('`', &(in_out_argv[i]))) 00863 { 00864 shell_PrintError(context, "Syntax error: Missing closing backquote"); 00865 error = SHELL_SYNTAX_ERROR; 00866 break; 00867 } 00868 00869 if(unescape(in_out_argv[i])) 00870 { 00871 shell_PrintError(context, "Syntax error: Invalid escape sequence"); 00872 error = SHELL_SYNTAX_ERROR; 00873 break; 00874 } 00875 00876 /* Parse command line */ 00877 00878 if(shell_ParseLine(in_out_argv[i], arglist, &argcount)) 00879 { 00880 error = SHELL_SYNTAX_ERROR; 00881 break; 00882 } 00883 00884 /* nothing to do if the command is empty. */ 00885 00886 if(argcount == 0) 00887 { 00888 00889 /* empty output */ 00890 in_out_argv[i][0] = '\0'; 00891 00892 /* command status */ 00893 shell_SetStatus(context, 0); 00894 00895 } 00896 else 00897 { 00898 00899 int fd[2]; 00900 FILE *output_stream; 00901 int alloctab[MAX_ARGS]; 00902 00903 char output_string[MAX_OUTPUT_LEN]; 00904 00905 /* Evaluates arguments */ 00906 00907 if(shell_SolveArgs(argcount, arglist, alloctab)) 00908 { 00909 error = SHELL_SYNTAX_ERROR; 00910 break; 00911 } 00912 00913 /* create pipe for command output */ 00914 00915 if(pipe(fd)) 00916 { 00917 00918 snprintf(tracebuff, TRACEBUFFSIZE, "Can't create pipe: %s (%d)", 00919 strerror(errno), errno); 00920 shell_PrintError(context, tracebuff); 00921 00922 /* clean allocated strings */ 00923 shell_CleanArgs(argcount, arglist, alloctab); 00924 00925 error = errno; 00926 break; 00927 00928 } 00929 00930 /* opening output stream */ 00931 00932 output_stream = fdopen(fd[1], "a"); 00933 00934 if(output_stream == NULL) 00935 { 00936 00937 snprintf(tracebuff, TRACEBUFFSIZE, "Can't open pipe stream: %s (%d)", 00938 strerror(errno), errno); 00939 shell_PrintError(context, tracebuff); 00940 00941 /* clean allocated strings */ 00942 shell_CleanArgs(argcount, arglist, alloctab); 00943 00944 /* close pipe */ 00945 close(fd[1]); 00946 close(fd[0]); 00947 00948 error = errno; 00949 break; 00950 00951 } 00952 00953 /* @todo : thread for pipe reading */ 00954 00955 /* Execute command */ 00956 00957 status = shell_Execute(argcount, arglist, output_stream); 00958 00959 /* closing ouput stream. */ 00960 00961 fclose(output_stream); 00962 close(fd[1]); 00963 00964 /* clean allocated strings */ 00965 shell_CleanArgs(argcount, arglist, alloctab); 00966 00967 /* read the output from pipe */ 00968 00969 rc = read(fd[0], output_string, MAX_OUTPUT_LEN); 00970 00971 /* close pipe */ 00972 close(fd[0]); 00973 00974 if(rc == -1) 00975 { 00976 snprintf(tracebuff, TRACEBUFFSIZE, "Cannot read from pipe: %s (%d)", 00977 strerror(errno), errno); 00978 shell_PrintError(context, tracebuff); 00979 00980 error = errno; 00981 break; 00982 } 00983 00984 /* allocate and fill output buffer */ 00985 00986 in_out_argv[i] = gsh_malloc(rc + 1); 00987 00988 if(in_out_argv[i] == NULL) 00989 { 00990 shell_PrintError(context, "Malloc error"); 00991 error = -1; 00992 break; 00993 } 00994 00995 memcpy(in_out_argv[i], output_string, rc); 00996 00997 out_allocated[i] = TRUE; 00998 00999 in_out_argv[i][rc] = '\0'; 01000 01001 /* set command status */ 01002 01003 shell_SetStatus(context, status); 01004 01005 } 01006 01007 } 01008 /* normal arg */ 01009 else 01010 { 01011 if(unescape(in_out_argv[i])) 01012 { 01013 shell_PrintError(context, "Syntax error: Invalid escape sequence"); 01014 error = SHELL_SYNTAX_ERROR; 01015 break; 01016 } 01017 01018 } /* in_out_argv[i][0] */ 01019 01020 } /* for */ 01021 01022 /* the case when we exited the for because of an error. */ 01023 01024 if(error) 01025 { 01026 /* free allocated strings */ 01027 shell_CleanArgs(i + 1, in_out_argv, out_allocated); 01028 return error; 01029 } 01030 01031 return SHELL_SUCCESS; 01032 01033 } /* shell_SolveArgs */ 01034 01045 void shell_CleanArgs(int argc, char **in_out_argv, int *in_allocated) 01046 { 01047 01048 int i; 01049 01050 for(i = 0; i < argc; i++) 01051 { 01052 01053 if(in_allocated[i]) 01054 { 01055 gsh_free(in_out_argv[i]); 01056 in_out_argv[i] = NULL; 01057 in_allocated[i] = FALSE; 01058 } 01059 01060 } 01061 01062 return; 01063 01064 } 01065 01076 int shell_Execute(int argc, char **argv, FILE * output) 01077 { 01078 01079 /* pointer to the command to be launched */ 01080 int (*command_func) (int, char **, FILE *) = NULL; 01081 01082 int i; 01083 int rc; 01084 char tracebuff[TRACEBUFFSIZE]; 01085 01086 shell_state_t *context = GetShellContext(); 01087 01088 /* First, look at shell internal commands */ 01089 01090 for(i = 0; shell_commands[i].command_name; i++) 01091 { 01092 if(!strcmp(argv[0], shell_commands[i].command_name)) 01093 { 01094 command_func = shell_commands[i].command_func; 01095 break; 01096 } 01097 } 01098 01099 /* If not found, look at shell utils commands */ 01100 01101 if(!command_func) 01102 { 01103 01104 for(i = 0; shell_utils[i].command_name; i++) 01105 { 01106 if(!strcmp(argv[0], shell_utils[i].command_name)) 01107 { 01108 command_func = shell_utils[i].command_func; 01109 break; 01110 } 01111 } 01112 01113 } 01114 01115 /* If not found, look at layer commands */ 01116 01117 if(!command_func) 01118 { 01119 layer_def_t *current_layer = shell_GetLayer(context); 01120 01121 if(current_layer) 01122 { 01123 01124 for(i = 0; current_layer->command_list[i].command_name; i++) 01125 { 01126 if(!strcmp(argv[0], current_layer->command_list[i].command_name)) 01127 { 01128 command_func = current_layer->command_list[i].command_func; 01129 01130 /* set layer's debug level */ 01131 current_layer->setlog_func(shell_GetDbgLvl(context)); 01132 01133 break; 01134 } 01135 } /* for */ 01136 01137 } 01138 /* if current_layer */ 01139 } 01140 01141 /* if command_func */ 01142 /* command not found */ 01143 if(!command_func) 01144 { 01145 snprintf(tracebuff, TRACEBUFFSIZE, "%s: command not found", argv[0]); 01146 shell_PrintError(context, tracebuff); 01147 return SHELL_NOT_FOUND; 01148 } 01149 01150 /* verbose trace */ 01151 01152 if(shell_GetVerbose(context)) 01153 { 01154 tracebuff[0] = '\0'; 01155 for(i = 0; i < argc; i++) 01156 { 01157 /* + 1 = size of the additional char ( + or space) */ 01158 size_t len1 = strlen(tracebuff) + 1; 01159 size_t len2 = strlen(argv[i]); 01160 01161 if(len1 > TRACEBUFFSIZE - 1) 01162 break; 01163 01164 if(i != 0) 01165 strcat(tracebuff, " "); 01166 else 01167 strcat(tracebuff, "+"); 01168 01169 if(len1 + len2 > TRACEBUFFSIZE - 1) 01170 { 01171 if(TRACEBUFFSIZE - 6 - len1 > 0) 01172 strncat(tracebuff, argv[i], TRACEBUFFSIZE - 6 - len1); 01173 01174 strcat(tracebuff, "[...]"); 01175 break; 01176 } 01177 else 01178 { 01179 strcat(tracebuff, argv[i]); 01180 } 01181 01182 } 01183 } 01184 shell_PrintTrace(context, tracebuff); 01185 01186 /* execute the command */ 01187 01188 rc = command_func(argc, argv, output); 01189 01190 /* verbose trace */ 01191 01192 snprintf(tracebuff, TRACEBUFFSIZE, "%s returned %d", argv[0], rc); 01193 shell_PrintTrace(context, tracebuff); 01194 01195 return rc; 01196 01197 } /* shell_Execute */ 01198 01199 /*------------------------------------------------------------------ 01200 * Shell ouput routines. 01201 *-----------------------------------------------------------------*/ 01202 01207 void shell_PrintError(shell_state_t * context, char *error_msg) 01208 { 01209 01210 char *input_name = get_var_value("INPUT"); 01211 01212 fprintf(stderr, "******* ERROR in %s line %d: %s\n", 01213 (input_name ? input_name : "?"), shell_GetLine(context), error_msg); 01214 01215 } 01216 01221 void shell_PrintTrace(shell_state_t * context, char *msg) 01222 { 01223 01224 char *input_name; 01225 01226 if(shell_GetVerbose(context)) 01227 { 01228 input_name = get_var_value("INPUT"); 01229 01230 fprintf(stderr, "%s l.%d: %s\n", 01231 (input_name ? input_name : "?"), shell_GetLine(context), msg); 01232 } 01233 01234 } 01235 01236 /*------------------------------------------------------------------ 01237 * Shell state management routines. 01238 *-----------------------------------------------------------------*/ 01239 01246 int shell_SetLayer(shell_state_t * context, char *layer_name) 01247 { 01248 01249 layer_def_t *layer = NULL; 01250 int i, rc; 01251 char tracebuff[TRACEBUFFSIZE]; 01252 01253 /* search for layer */ 01254 01255 for(i = 0; layer_list[i].layer_name; i++) 01256 { 01257 if(!strcasecmp(layer_name, layer_list[i].layer_name)) 01258 { 01259 layer = &layer_list[i]; 01260 break; 01261 } 01262 } 01263 01264 /* saves current layer */ 01265 01266 if(layer) 01267 { 01268 /* saves layer pointer */ 01269 01270 context->layer = layer; 01271 01272 /* stores layer name into vars */ 01273 01274 rc = set_var_value("LAYER", layer->layer_name); 01275 01276 if(rc != 0) 01277 { 01278 snprintf(tracebuff, TRACEBUFFSIZE, 01279 "Error %d setting LAYER value to %s", rc, layer->layer_name); 01280 shell_PrintError(context, tracebuff); 01281 } 01282 01283 snprintf(tracebuff, TRACEBUFFSIZE, "Current layer is now %s", layer->layer_name); 01284 shell_PrintTrace(context, tracebuff); 01285 01286 return SHELL_SUCCESS; 01287 01288 } 01289 else 01290 { 01291 snprintf(tracebuff, TRACEBUFFSIZE, "Layer not found: %s", layer_name); 01292 shell_PrintError(context, tracebuff); 01293 return SHELL_NOT_FOUND; 01294 } 01295 01296 } /* shell_SetLayer */ 01297 01302 layer_def_t *shell_GetLayer(shell_state_t * context) 01303 { 01304 01305 return context->layer; 01306 01307 } 01308 01313 int shell_SetStatus(shell_state_t * context, int returned_status) 01314 { 01315 01316 int rc; 01317 char str_int[64]; 01318 char tracebuff[TRACEBUFFSIZE]; 01319 01320 context->status = returned_status; 01321 01322 snprintf(str_int, 64, "%d", returned_status); 01323 01324 rc = set_var_value("STATUS", str_int); 01325 01326 if(rc != 0) 01327 { 01328 snprintf(tracebuff, TRACEBUFFSIZE, 01329 "Error %d setting STATUS value to %s", rc, str_int); 01330 shell_PrintError(context, tracebuff); 01331 } 01332 01333 rc = set_var_value("?", str_int); 01334 01335 if(rc != 0) 01336 { 01337 snprintf(tracebuff, TRACEBUFFSIZE, "Error %d setting ? value to %s", rc, str_int); 01338 shell_PrintError(context, tracebuff); 01339 } 01340 01341 return SHELL_SUCCESS; 01342 01343 } 01344 01349 int shell_GetStatus(shell_state_t * context) 01350 { 01351 return context->status; 01352 } 01353 01358 int shell_SetVerbose(shell_state_t * context, char *str_verbose) 01359 { 01360 01361 int rc; 01362 char tracebuff[TRACEBUFFSIZE]; 01363 01364 if(!strcasecmp(str_verbose, "ON") || 01365 !strcasecmp(str_verbose, "TRUE") || 01366 !strcasecmp(str_verbose, "YES") || !strcmp(str_verbose, "1")) 01367 { 01368 context->verbose = TRUE; 01369 01370 rc = set_var_value("VERBOSE", "1"); 01371 01372 if(rc != 0) 01373 { 01374 snprintf(tracebuff, TRACEBUFFSIZE, 01375 "Error %d setting VERBOSE value to %s", rc, "1"); 01376 shell_PrintError(context, tracebuff); 01377 } 01378 01379 return SHELL_SUCCESS; 01380 01381 } 01382 else if(!strcasecmp(str_verbose, "OFF") || 01383 !strcasecmp(str_verbose, "FALSE") || 01384 !strcasecmp(str_verbose, "NO") || !strcmp(str_verbose, "0")) 01385 { 01386 context->verbose = FALSE; 01387 01388 rc = set_var_value("VERBOSE", "0"); 01389 01390 if(rc != 0) 01391 { 01392 snprintf(tracebuff, TRACEBUFFSIZE, 01393 "Error %d setting VERBOSE value to %s", rc, "0"); 01394 shell_PrintError(context, tracebuff); 01395 } 01396 01397 return SHELL_SUCCESS; 01398 01399 } 01400 else 01401 { 01402 snprintf(tracebuff, TRACEBUFFSIZE, "Unexpected value for VERBOSE: %s", str_verbose); 01403 shell_PrintError(context, tracebuff); 01404 01405 return SHELL_SYNTAX_ERROR; 01406 } 01407 01408 } 01409 01414 int shell_GetVerbose(shell_state_t * context) 01415 { 01416 return context->verbose; 01417 } 01418 01423 int shell_SetDbgLvl(shell_state_t * context, char *str_debug_level) 01424 { 01425 int level_debug; 01426 int rc; 01427 char tracebuff[TRACEBUFFSIZE]; 01428 01429 level_debug = ReturnLevelAscii(str_debug_level); 01430 01431 if(level_debug != -1) 01432 { 01433 /* set shell state */ 01434 context->debug_level = level_debug; 01435 01436 /* call to logfunctions */ 01437 SetLevelDebug(level_debug); 01438 01439 /* set shell vars */ 01440 01441 rc = set_var_value("DEBUG_LEVEL", str_debug_level); 01442 01443 if(rc != 0) 01444 { 01445 snprintf(tracebuff, TRACEBUFFSIZE, 01446 "Error %d setting DEBUG_LEVEL value to %s", rc, str_debug_level); 01447 shell_PrintError(context, tracebuff); 01448 } 01449 01450 rc = set_var_value("DBG_LVL", str_debug_level); 01451 01452 if(rc != 0) 01453 { 01454 snprintf(tracebuff, TRACEBUFFSIZE, 01455 "Error %d setting DBG_LVL value to %s", rc, str_debug_level); 01456 shell_PrintError(context, tracebuff); 01457 } 01458 01459 return SHELL_SUCCESS; 01460 01461 } 01462 else 01463 { 01464 01465 snprintf(tracebuff, TRACEBUFFSIZE, 01466 "Unexpected value for DEBUG_LEVEL: %s", str_debug_level); 01467 shell_PrintError(context, tracebuff); 01468 01469 return SHELL_SYNTAX_ERROR; 01470 } 01471 01472 } /* shell_SetDbgLvl */ 01473 01478 int shell_GetDbgLvl(shell_state_t * context) 01479 { 01480 return context->debug_level; 01481 } 01482 01491 int shell_SetInput(shell_state_t * context, char *file_name) 01492 { 01493 01494 FILE *stream; 01495 int rc; 01496 char tracebuff[TRACEBUFFSIZE]; 01497 01498 if(file_name) 01499 { 01500 if((stream = fopen(file_name, "r")) == NULL) 01501 { 01502 snprintf(tracebuff, TRACEBUFFSIZE, "Can't open \"%s\": %s (%d)", 01503 file_name, strerror(errno), errno); 01504 shell_PrintError(context, tracebuff); 01505 return errno; 01506 } 01507 01508 /* close previous filestream and reset line number */ 01509 if(context->input_stream != NULL) 01510 { 01511 /* don't close stdin */ 01512 if(context->input_stream != stdin) 01513 fclose(context->input_stream); 01514 01515 shell_SetLine(context, 0); 01516 } 01517 01518 /* set filestream */ 01519 context->input_stream = stream; 01520 01521 rc = set_var_value("INPUT", file_name); 01522 01523 if(rc != 0) 01524 { 01525 snprintf(tracebuff, TRACEBUFFSIZE, 01526 "Error %d setting INPUT value to \"%s\"", rc, file_name); 01527 shell_PrintError(context, tracebuff); 01528 } 01529 01530 /* set interative mode to FALSE */ 01531 01532 context->interactive = FALSE; 01533 01534 rc = set_var_value("INTERACTIVE", "0"); 01535 01536 if(rc != 0) 01537 { 01538 snprintf(tracebuff, TRACEBUFFSIZE, 01539 "Error %d setting INTERACTIVE value to %s", rc, "0"); 01540 shell_PrintError(context, tracebuff); 01541 } 01542 01543 snprintf(tracebuff, TRACEBUFFSIZE, "Using script file \"%s\"", file_name); 01544 shell_PrintTrace(context, tracebuff); 01545 01546 return SHELL_SUCCESS; 01547 01548 } 01549 else 01550 { 01551 stream = stdin; 01552 01553 /* close previous filestream and reset line number */ 01554 if(context->input_stream != NULL) 01555 { 01556 /* don't close stdin */ 01557 if(context->input_stream != stdin) 01558 fclose(context->input_stream); 01559 shell_SetLine(context, 0); 01560 } 01561 01562 /* set filestream */ 01563 context->input_stream = stream; 01564 01565 rc = set_var_value("INPUT", "<stdin>"); 01566 01567 if(rc != 0) 01568 { 01569 snprintf(tracebuff, TRACEBUFFSIZE, 01570 "Error %d setting INPUT value to %s", rc, "<stdin>"); 01571 shell_PrintError(context, tracebuff); 01572 } 01573 01574 /* set interative mode to TRUE */ 01575 01576 context->interactive = TRUE; 01577 01578 rc = set_var_value("INTERACTIVE", "1"); 01579 01580 if(rc != 0) 01581 { 01582 snprintf(tracebuff, TRACEBUFFSIZE, 01583 "Error %d setting INTERACTIVE value to %s", rc, "1"); 01584 shell_PrintError(context, tracebuff); 01585 } 01586 01587 snprintf(tracebuff, TRACEBUFFSIZE, "Using standard input"); 01588 shell_PrintTrace(context, tracebuff); 01589 01590 return SHELL_SUCCESS; 01591 01592 } 01593 01594 } /* shell_SetInput */ 01595 01600 FILE *shell_GetInputStream(shell_state_t * context) 01601 { 01602 if(context->input_stream) 01603 return context->input_stream; 01604 else 01605 return stdin; 01606 } 01607 01612 int shell_SetPrompt(shell_state_t * context, char *str_prompt) 01613 { 01614 int rc = set_var_value("PROMPT", str_prompt); 01615 char tracebuff[TRACEBUFFSIZE]; 01616 01617 if(rc != 0) 01618 { 01619 snprintf(tracebuff, TRACEBUFFSIZE, 01620 "Error %d setting PROMPT value to \"%s\"", rc, str_prompt); 01621 shell_PrintError(context, tracebuff); 01622 } 01623 01624 return rc; 01625 } 01626 01631 char *shell_GetPrompt(shell_state_t * context) 01632 { 01633 return get_var_value("PROMPT"); 01634 } 01635 01640 int shell_SetShellId(shell_state_t * context, int shell_index) 01641 { 01642 int rc; 01643 char str[64]; 01644 char tracebuff[TRACEBUFFSIZE]; 01645 01646 snprintf(str, 64, "%d", shell_index); 01647 01648 rc = set_var_value("SHELLID", str); 01649 01650 if(rc != 0) 01651 { 01652 snprintf(tracebuff, TRACEBUFFSIZE, 01653 "Error %d setting SHELLID value to \"%s\"", rc, str); 01654 shell_PrintError(context, tracebuff); 01655 } 01656 01657 return SHELL_SUCCESS; 01658 } 01659 01664 int shell_SetLine(shell_state_t * context, int lineno) 01665 { 01666 int rc; 01667 char str_line[64]; 01668 char tracebuff[TRACEBUFFSIZE]; 01669 01670 context->line = lineno; 01671 01672 snprintf(str_line, 64, "%d", lineno); 01673 01674 rc = set_var_value("LINE", str_line); 01675 01676 if(rc != 0) 01677 { 01678 snprintf(tracebuff, TRACEBUFFSIZE, 01679 "Error %d setting LINE value to \"%s\"", rc, str_line); 01680 shell_PrintError(context, tracebuff); 01681 } 01682 01683 return SHELL_SUCCESS; 01684 01685 } 01686 01691 int shell_GetLine(shell_state_t * context) 01692 { 01693 return context->line; 01694 } 01695 01696 /*------------------------------------------------------------------ 01697 * Shell commands. 01698 *-----------------------------------------------------------------*/ 01699 01700 int shellcmd_help(int argc, /* IN : number of args in argv */ 01701 char **argv, /* IN : arg list */ 01702 FILE * output /* IN : output stream */ 01703 ) 01704 { 01705 01706 int i; 01707 char tracebuff[TRACEBUFFSIZE]; 01708 layer_def_t *current_layer = shell_GetLayer(GetShellContext()); 01709 01710 /* check args */ 01711 01712 if(argc > 1) 01713 { 01714 for(i = 1; i < argc; i++) 01715 { 01716 snprintf(tracebuff, TRACEBUFFSIZE, 01717 "%s: Unexpected argument \"%s\"", argv[0], argv[i]); 01718 shell_PrintError(GetShellContext(), tracebuff); 01719 } 01720 } 01721 01722 /* List shell build-in commands */ 01723 01724 fprintf(output, "Shell built-in commands:\n"); 01725 01726 for(i = 0; shell_commands[i].command_name; i++) 01727 { 01728 fprintf(output, " %15s: %s\n", shell_commands[i].command_name, 01729 shell_commands[i].command_help); 01730 } 01731 01732 /* List shell tools commands */ 01733 01734 fprintf(output, "\nShell tools commands:\n"); 01735 01736 for(i = 0; shell_utils[i].command_name; i++) 01737 { 01738 fprintf(output, " %15s: %s\n", shell_utils[i].command_name, 01739 shell_utils[i].command_help); 01740 } 01741 01742 /* Layer list */ 01743 01744 fprintf(output, "\nLayers list:\n"); 01745 01746 for(i = 0; layer_list[i].layer_name; i++) 01747 { 01748 fprintf(output, " %15s: %s\n", layer_list[i].layer_name, 01749 layer_list[i].layer_description); 01750 } 01751 01752 /* Layer commands */ 01753 01754 if(current_layer) 01755 { 01756 01757 fprintf(output, "\n%s layer commands:\n", current_layer->layer_name); 01758 01759 for(i = 0; current_layer->command_list[i].command_name; i++) 01760 { 01761 fprintf(output, " %15s: %s\n", current_layer->command_list[i].command_name, 01762 current_layer->command_list[i].command_help); 01763 } 01764 01765 } 01766 01767 return SHELL_SUCCESS; 01768 01769 } /* shellcmd_help */ 01770 01771 int shellcmd_if(int argc, /* IN : number of args in argv */ 01772 char **argv, /* IN : arg list */ 01773 FILE * output /* IN : output stream */ 01774 ) 01775 { 01776 01777 int i, rc; 01778 int index_test = -1; 01779 int longueur_test = -1; 01780 int index_cmd1 = -1; 01781 int longueur_cmd1 = -1; 01782 int index_cmd2 = -1; 01783 int longueur_cmd2 = -1; 01784 01785 const char *help_if = 01786 "Usage: if command0 ? command1 [: command2]\n" 01787 " Execute command1 if command0 returns a null status.\n" 01788 " Else, execute command2 (if any).\n" 01789 "Ex: if eq -n $STATUS 0 ? print \"status=0\" : print \"status<>0\" \n"; 01790 01791 /* first, check that there is a test */ 01792 if(argc > 1) 01793 { 01794 01795 index_test = 1; 01796 01797 i = index_test + 1; 01798 01799 /* look for command 1 */ 01800 01801 while((i < argc) && strcmp(argv[i], "?")) 01802 i++; 01803 01804 if(i + 1 < argc) 01805 { 01806 longueur_test = i - index_test; 01807 index_cmd1 = i + 1; 01808 01809 i = index_cmd1 + 1; 01810 01811 /* look for command 2 */ 01812 01813 while((i < argc) && strcmp(argv[i], ":")) 01814 i++; 01815 01816 if(i + 1 < argc) 01817 { 01818 longueur_cmd1 = i - index_cmd1; 01819 index_cmd2 = i + 1; 01820 longueur_cmd2 = argc - index_cmd2; 01821 } 01822 else 01823 { 01824 longueur_cmd1 = argc - index_cmd1; 01825 } 01826 01827 } 01828 else 01829 { 01830 longueur_test = argc - index_test; 01831 } 01832 01833 } 01834 01835 /* test or cmd1 missing */ 01836 01837 if((longueur_test <= 0) || (longueur_cmd1 <= 0)) 01838 { 01839 fprintf(output, help_if, NULL); 01840 return SHELL_SYNTAX_ERROR; 01841 } 01842 01843 /* executes test */ 01844 01845 rc = shell_Execute(longueur_test, &(argv[index_test]), output); 01846 01847 /* if rc is not null, executes command 1 */ 01848 if(rc) 01849 { 01850 return shell_Execute(longueur_cmd1, &(argv[index_cmd1]), output); 01851 } 01852 else if(longueur_cmd2 > 0) 01853 { 01854 return shell_Execute(longueur_cmd2, &(argv[index_cmd2]), output); 01855 } 01856 01857 return 0; 01858 01859 } /* shellcmd_if */ 01860 01861 int shellcmd_interactive(int argc, /* IN : number of args in argv */ 01862 char **argv, /* IN : arg list */ 01863 FILE * output /* IN : output stream */ 01864 ) 01865 { 01866 int i; 01867 char tracebuff[TRACEBUFFSIZE]; 01868 01869 /* check args */ 01870 01871 if(argc > 1) 01872 { 01873 for(i = 1; i < argc; i++) 01874 { 01875 snprintf(tracebuff, TRACEBUFFSIZE, 01876 "%s: Unexpected argument \"%s\"", argv[0], argv[i]); 01877 shell_PrintError(GetShellContext(), tracebuff); 01878 } 01879 } 01880 01881 /* set input as stdin */ 01882 01883 return shell_SetInput(GetShellContext(), NULL); 01884 01885 } /* shellcmd_interactive */ 01886 01887 int shellcmd_set(int argc, /* IN : number of args in argv */ 01888 char **argv, /* IN : arg list */ 01889 FILE * output /* IN : output stream */ 01890 ) 01891 { 01892 01893 int i; 01894 char *varname; 01895 char tracebuff[TRACEBUFFSIZE]; 01896 char varvalue[MAX_OUTPUT_LEN]; 01897 01898 /* check args */ 01899 01900 if(argc < 3) 01901 { 01902 snprintf(tracebuff, TRACEBUFFSIZE, 01903 "%s: Usage: %s <var_name> <expr1> [<expr2> ...<exprN>]", argv[0], argv[0]); 01904 shell_PrintError(GetShellContext(), tracebuff); 01905 01906 return SHELL_SYNTAX_ERROR; 01907 } 01908 01909 varname = argv[1]; 01910 01911 varvalue[0] = '\0'; 01912 01913 /* concatenation of strings */ 01914 01915 for(i = 2; i < argc; i++) 01916 if(concat(varvalue, argv[i], MAX_OUTPUT_LEN) == NULL) 01917 { 01918 shell_PrintError(GetShellContext(), "Output too large."); 01919 return SHELL_ERROR; 01920 } 01921 01922 /* special variables */ 01923 01924 if(!strcmp(varname, "INPUT")) 01925 { 01926 return shell_SetInput(GetShellContext(), varvalue); 01927 } 01928 else if(!strcmp(varname, "INTERACTIVE")) 01929 { 01930 snprintf(tracebuff, TRACEBUFFSIZE, 01931 "%s: cannot set \"%s\": set the value of \"INPUT\" or use the \"interactive\" command instead.", 01932 argv[0], varname); 01933 shell_PrintError(GetShellContext(), tracebuff); 01934 01935 return SHELL_ERROR; 01936 01937 } 01938 else if(!strcmp(varname, "LAYER")) 01939 { 01940 return shell_SetLayer(GetShellContext(), varvalue); 01941 } 01942 else if(!strcmp(varname, "STATUS") || !strcmp(varname, "?")) 01943 { 01944 return shell_SetStatus(GetShellContext(), my_atoi(varvalue)); 01945 } 01946 else if(!strcmp(varname, "VERBOSE")) 01947 { 01948 return shell_SetVerbose(GetShellContext(), varvalue); 01949 } 01950 else if(!strcmp(varname, "DEBUG_LEVEL") || !strcmp(varname, "DBG_LVL")) 01951 { 01952 return shell_SetDbgLvl(GetShellContext(), varvalue); 01953 } 01954 else if(!strcmp(varname, "PROMPT")) 01955 { 01956 return shell_SetPrompt(GetShellContext(), varvalue); 01957 } 01958 else if(!strcmp(varname, "LINE")) 01959 { 01960 snprintf(tracebuff, TRACEBUFFSIZE, "%s: cannot set \"%s\".", argv[0], varname); 01961 shell_PrintError(GetShellContext(), tracebuff); 01962 return SHELL_ERROR; 01963 } 01964 else 01965 { 01966 01967 /* other variables */ 01968 01969 if(!is_authorized_varname(varname)) 01970 { 01971 snprintf(tracebuff, TRACEBUFFSIZE, "%s: Invalid variable name \"%s\".", argv[0], 01972 varname); 01973 shell_PrintError(GetShellContext(), tracebuff); 01974 return SHELL_ERROR; 01975 } 01976 01977 if(set_var_value(varname, varvalue)) 01978 { 01979 snprintf(tracebuff, TRACEBUFFSIZE, "%s: Error setting the value of \"%s\".", 01980 argv[0], varname); 01981 shell_PrintError(GetShellContext(), tracebuff); 01982 return SHELL_ERROR; 01983 } 01984 01985 return SHELL_SUCCESS; 01986 01987 } 01988 01989 /* should never happen */ 01990 return SHELL_ERROR; 01991 01992 } /* shellcmd_set */ 01993 01994 int shellcmd_unset(int argc, /* IN : number of args in argv */ 01995 char **argv, /* IN : arg list */ 01996 FILE * output /* IN : output stream */ 01997 ) 01998 { 01999 02000 int i, arg_idx; 02001 char tracebuff[TRACEBUFFSIZE]; 02002 int error = SHELL_SUCCESS; 02003 02004 if(argc <= 1) 02005 { 02006 snprintf(tracebuff, TRACEBUFFSIZE, "%s: Missing argument: <var name>", argv[0]); 02007 shell_PrintError(GetShellContext(), tracebuff); 02008 02009 return SHELL_SYNTAX_ERROR; 02010 } 02011 02012 for(arg_idx = 1; arg_idx < argc; arg_idx++) 02013 { 02014 02015 /* check if it is not a special var */ 02016 02017 for(i = 0; shell_special_vars[i] != NULL; i++) 02018 { 02019 02020 if(!strcmp(shell_special_vars[i], argv[arg_idx])) 02021 { 02022 02023 snprintf(tracebuff, TRACEBUFFSIZE, 02024 "%s: This special variable cannot be deleted: \"%s\"", argv[0], 02025 argv[arg_idx]); 02026 shell_PrintError(GetShellContext(), tracebuff); 02027 02028 return SHELL_ERROR; 02029 02030 } 02031 02032 } 02033 02034 /* unset the variable */ 02035 02036 if(free_var(argv[arg_idx])) 02037 { 02038 snprintf(tracebuff, TRACEBUFFSIZE, 02039 "%s: Variable not found: \"%s\"", argv[0], argv[arg_idx]); 02040 shell_PrintError(GetShellContext(), tracebuff); 02041 02042 error = SHELL_NOT_FOUND; 02043 /* however, continue */ 02044 } 02045 02046 } 02047 02048 return error; 02049 02050 } /* shellcmd_unset */ 02051 02052 int shellcmd_print(int argc, /* IN : number of args in argv */ 02053 char **argv, /* IN : arg list */ 02054 FILE * output /* IN : output stream */ 02055 ) 02056 { 02057 02058 int i; 02059 02060 /* print args */ 02061 for(i = 1; i < argc; i++) 02062 fprintf(output, "%s", argv[i]); 02063 02064 fprintf(output, "\n"); 02065 02066 return 0; 02067 02068 } /* shellcmd_print */ 02069 02070 int shellcmd_varlist(int argc, /* IN : number of args in argv */ 02071 char **argv, /* IN : arg list */ 02072 FILE * output /* IN : output stream */ 02073 ) 02074 { 02075 int i; 02076 char tracebuff[TRACEBUFFSIZE]; 02077 02078 /* check args */ 02079 02080 if(argc > 1) 02081 { 02082 for(i = 1; i < argc; i++) 02083 { 02084 snprintf(tracebuff, TRACEBUFFSIZE, 02085 "%s: Unexpected argument \"%s\"", argv[0], argv[i]); 02086 shell_PrintError(GetShellContext(), tracebuff); 02087 } 02088 } 02089 02090 print_varlist(output, shell_GetVerbose(GetShellContext())); 02091 02092 return 0; 02093 02094 } /* shellcmd_varlist */ 02095 02096 int shellcmd_time(int argc, /* IN : number of args in argv */ 02097 char **argv, /* IN : arg list */ 02098 FILE * output /* IN : output stream */ 02099 ) 02100 { 02101 02102 const char help_time[] = 02103 "Usage: time command [args ...]\n" 02104 " Measure the time for executing a command.\n" "Ex: time shell ls\n"; 02105 02106 struct timeval timer_start; 02107 struct timeval timer_stop; 02108 struct timeval timer_tmp; 02109 02110 int rc; 02111 02112 /* first, check that there is a test */ 02113 if(argc < 2) 02114 { 02115 fprintf(output, help_time); 02116 return SHELL_SYNTAX_ERROR; 02117 } 02118 02119 if(gettimeofday(&timer_start, NULL) == -1) 02120 { 02121 fprintf(output, "Error retrieving system time.\n"); 02122 return SHELL_ERROR; 02123 } 02124 02125 rc = shell_Execute(argc - 1, &(argv[1]), output); 02126 02127 if(gettimeofday(&timer_stop, NULL) == -1) 02128 { 02129 fprintf(output, "Error retrieving system time.\n"); 02130 return SHELL_ERROR; 02131 } 02132 02133 timer_tmp = time_diff(timer_start, timer_stop); 02134 fprintf(output, "\nExecution time for command \"%s\": ", argv[1]); 02135 print_timeval(output, timer_tmp); 02136 02137 return rc; 02138 02139 } /* shellcmd_time */ 02140 02141 int shellcmd_quit(int argc, /* IN : number of args in argv */ 02142 char **argv, /* IN : arg list */ 02143 FILE * output /* IN : output stream */ 02144 ) 02145 { 02146 int i; 02147 char tracebuff[TRACEBUFFSIZE]; 02148 02149 /* check args */ 02150 02151 if(argc > 1) 02152 { 02153 for(i = 1; i < argc; i++) 02154 { 02155 snprintf(tracebuff, TRACEBUFFSIZE, 02156 "%s: Unexpected argument \"%s\"", argv[0], argv[i]); 02157 shell_PrintError(GetShellContext(), tracebuff); 02158 } 02159 } 02160 02161 exit(0); 02162 return 0; 02163 02164 } /* shellcmd_quit */ 02165 02166 int shellcmd_barrier(int argc, /* IN : number of args in argv */ 02167 char **argv, /* IN : arg list */ 02168 FILE * output /* IN : output stream */ 02169 ) 02170 { 02171 int i; 02172 char tracebuff[TRACEBUFFSIZE]; 02173 02174 /* check args */ 02175 02176 if(argc > 1) 02177 { 02178 for(i = 1; i < argc; i++) 02179 { 02180 snprintf(tracebuff, TRACEBUFFSIZE, 02181 "%s: Unexpected argument \"%s\"", argv[0], argv[i]); 02182 shell_PrintError(GetShellContext(), tracebuff); 02183 } 02184 } 02185 02186 /* call shell_BarrierWait */ 02187 02188 if(shell_BarrierWait()) 02189 { 02190 snprintf(tracebuff, TRACEBUFFSIZE, 02191 "%s: barrier cannot be used in a single thread/script environment.", 02192 argv[0]); 02193 shell_PrintError(GetShellContext(), tracebuff); 02194 return SHELL_ERROR; 02195 } 02196 02197 return SHELL_SUCCESS; 02198 02199 } /* shellcmd_quit */