Changeset 23 for trunk/src/kShell
- Timestamp:
- Nov 22, 2002, 5:00:46 AM (23 years ago)
- Location:
- trunk/src/kShell
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kShell/kShell.c
r19 r23 23 23 * 24 24 */ 25 26 /** @design kShell (Micro Shell) 27 * 28 * The micro shell provides the basic shell functionality kBuild need - no more, 29 * no less. It is intended to be as simple as possible. 30 * 31 * The shell commands are case sensitive - all lowercase. 32 * 33 * The shell environment variables are case sensitive or insensitive according to 34 * host os. 35 * 36 * 37 * 38 * @subsection Command Separators 39 * 40 * There is one command separator '&&'. This works like splitting the command line 41 * into several makefile lines. This splitting isn't done by the micro shell but 42 * the makefile interpreter. 43 * 44 * You might thing this is limiting, but no, you can use all the makefile command 45 * prefixes. 46 * 47 * 48 * 49 * @subsection Path Component Separator (/) 50 * 51 * The shell uses '/' as path component separator. 52 * For host OSes with the notion of drive letters or similar, ':' is 53 * used to separate the drive letter and the path. 54 * 55 * 56 * 57 * @subsection UNC paths 58 * 59 * For host OSes which supports UNC paths these are supported but for the chdir 60 * command. 61 * 62 * The Path Component Separator is still '/' for UNC paths. 63 * 64 * 65 * 66 * @subsection Wildchars 67 * 68 * '*' and '?' are accepted as wildchars. 69 * 70 * '*' means 0 or more characters. <br> 71 * '?' means 1 character. 72 * 73 * When the term 'pattern' is use in command description this means that 74 * wildchars are accepted. 75 * 76 * 77 * 78 * @subsection Quoting 79 * 80 * Use double quotes (") to quote filenames or executables containing spaces. 81 * 82 * 83 * 84 * @subsection Execute Program 85 * 86 * If the first, possibly quoted, word of a commandline if not found as an 87 * internal command will be tried executed. If no path it will be searched 88 * for in the PATH environment variable. 89 * 90 * 91 * 92 * @subsection Commands 93 * 94 * This section will describe the commands implemented by the shell. 95 * 96 * 97 * 98 * @subsubsection copy 99 * Copies one or more files to a target file or directory. 100 * 101 * <b>Syntax: copy <source file pattern> [more sources] <target> </b> 102 * 103 * Specify one or more source file patterns. 104 * 105 * Specify exactly one target. The target may be a directory or a file. 106 * If it's a file and multiple source files specified either thru pattern or 107 * multiple source file specifications, the target file will be a copy of the 108 * last one. 109 * 110 * The command fails if a source file isn't found. It also fails on read or 111 * write errors. 112 * 113 * 114 * 115 * @subsubsection copytree 116 * Copies one or more files to a target file or directory. 117 * 118 * <b>Syntax: copytree <source directory> <target directory> </b> 119 * 120 * Specify exactly one source directory. 121 * 122 * Specify exactly one target directory. The target directory path will be 123 * created if doesn't exist. 124 * 125 * The command fails if source directory isn't found. It also fails on read or 126 * write errors. 127 * 128 * 129 * 130 * @subsubsection rm 131 * Deletes one or more files. 132 * 133 * <b>Syntax: rm [file pattern] [more files] </b> 134 * 135 * Specify 0 or more file patterns for deletion. 136 * 137 * This command fails if it cannot delete a file. It will not fail if a file 138 * doesn't exist. It will neither fail if no files are specified. 139 * 140 * 141 * 142 * @subsubsection rmtree 143 * Deletes one or more directory trees. 144 * 145 * <b>Syntax: rmtree [directory pattern] [directories] </b> 146 * 147 * Specify 0 or more directory patterns for deletion. 148 * 149 * This command fails if it cannot delete a file or directory. It will not fail 150 * if a directory doesn't exist. It will neither fail if no files are specified. 151 * 152 * 153 * 154 * @subsubsection chdir 155 * Changes the current directory. 156 * 157 * This updates the .CWD macro to the new current directory path. 158 * 159 * <b>Syntax: chdir <directory> </b> 160 * 161 * 162 * 163 * @subsubsection mkdir 164 * Create directory. 165 * 166 * <b>Syntax: mkdir <directory> </b> 167 * 168 * Specify one directory to create. 169 * 170 * 171 * 172 * @subsubsection rmdir 173 * Remove directory. 174 * 175 * <b>Syntax: rmdir <directory> </b> 176 * 177 * Specify one directory to remove. The directory must be empty. 178 * 179 * This command failes if directory isn't empty. It will not fail if 180 * the directory doesn't exist. 181 * 182 * 183 * 184 * @subsubsection set 185 * Set environment variable. 186 * 187 * <b>Syntax: set <envvar>=<value> </b> 188 * 189 * 190 * 191 * @subsubsection unset 192 * Unset enviornment variable(s). 193 * 194 * <b>Syntax: unset <envvar pattern> [more envvars] </b> 195 * 196 * Specify on or more environment variable patterns. 197 * 198 * 199 * 200 * @subsubsection pushenv 201 * Pushes a set of environment variables onto the environment stack. The 202 * variables can later be popped back using the popenv command. 203 * 204 * If '*' is specified as pattern the complete enviornment is pushed and 205 * when popped it will <b>replace</b> the enviornment. 206 * 207 * <b>Syntax: pushenv <envvar pattern> [more envvars] </b> 208 * <b>Syntax: pushenv * </b> 209 * 210 * 211 * 212 * @subsubsection popenv 213 * Pop a set of environment variables from the environment stack. If a '*' 214 * push was done, we'll replace the enviornment with the variables poped off 215 * the stack. 216 * 217 * <b>Syntax: popenv </b> 218 * 219 * 220 * 221 */ 222 25 223 26 224 /******************************************************************************* … … 33 231 #define KSHELL_MAX_COMMAND 4096 34 232 233 /** 234 * Test if this is an escapable character or not. 235 */ 236 #define KSHELL_ESCAPABLE(ch) ( (ch) == '"' \ 237 || (ch) == '\'' \ 238 || (ch) == '`' \ 239 || (ch) == 'ï' \ 240 ) 241 242 /** 243 * Test if this is a quote character or not. 244 */ 245 #define KSHELL_QUOTE(ch) ( (ch) == '"' \ 246 || (ch) == '\'' \ 247 || (ch) == '`' \ 248 || (ch) == 'ï' \ 249 ) 250 251 /** 252 * Test if this is a wildchar character or not. 253 */ 254 #define KSHELL_WILDCHAR(ch) ( (ch) == '*' || (ch) == '?' ) 255 256 257 35 258 /******************************************************************************* 36 259 * Header Files * 37 260 *******************************************************************************/ 38 261 #include "kShell.h" 262 #include <kLib/kLib.h> 263 #include <kLib/kString.h> 264 39 265 #include <string.h> 40 266 #include <stdlib.h> … … 63 289 64 290 /******************************************************************************* 291 * Global Variables * 292 *******************************************************************************/ 293 static const char *pszkshellCurDir = NULL; 294 295 /******************************************************************************* 65 296 * Internal Functions * 66 297 *******************************************************************************/ … … 68 299 void kshellWordsDestroy(PKSHELLWORDS pWords); 69 300 70 int kshellCmdcopy(const char *pszCmd, PKSHELLWORDS pWords); 71 int kshellCmdcopytree(const char *pszCmd, PKSHELLWORDS pWords); 72 int kshellCmdrm(const char *pszCmd, PKSHELLWORDS pWords); 73 int kshellCmdrmtree(const char *pszCmd, PKSHELLWORDS pWords); 74 int kshellCmdchdir(const char *pszCmd, PKSHELLWORDS pWords); 75 int kshellCmdmkdir(const char *pszCmd, PKSHELLWORDS pWords); 76 int kshellCmdrmdir(const char *pszCmd, PKSHELLWORDS pWords); 77 int kshellCmdset(const char *pszCmd, PKSHELLWORDS pWords); 78 int kshellCmdunset(const char *pszCmd, PKSHELLWORDS pWords); 79 int kshellCmdpushenv(const char *pszCmd, PKSHELLWORDS pWords); 80 int kshellCmdpopenv(const char *pszCmd, PKSHELLWORDS pWords); 81 int kshellCmdecho(const char *pszCmd, PKSHELLWORDS pWords); 82 int kshellCmdwrite(const char *pszCmd, PKSHELLWORDS pWords); 83 int kshellCmdExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords); 301 int kshellSyntaxError(const char *pszCmd, const char *pszMessage); 302 int kshellError(const char *pszCmd, const char *pszMessage); 303 304 int kshellCmd_copy(const char *pszCmd, PKSHELLWORDS pWords); 305 int kshellCmd_copytree(const char *pszCmd, PKSHELLWORDS pWords); 306 int kshellCmd_sync(const char *pszCmd, PKSHELLWORDS pWords); 307 int kshellCmd_synctree(const char *pszCmd, PKSHELLWORDS pWords); 308 int kshellCmd_rm(const char *pszCmd, PKSHELLWORDS pWords); 309 int kshellCmd_rmtree(const char *pszCmd, PKSHELLWORDS pWords); 310 int kshellCmd_chdir(const char *pszCmd, PKSHELLWORDS pWords); 311 int kshellCmd_mkdir(const char *pszCmd, PKSHELLWORDS pWords); 312 int kshellCmd_rmdir(const char *pszCmd, PKSHELLWORDS pWords); 313 int kshellCmd_set(const char *pszCmd, PKSHELLWORDS pWords); 314 int kshellCmd_unset(const char *pszCmd, PKSHELLWORDS pWords); 315 int kshellCmd_pushenv(const char *pszCmd, PKSHELLWORDS pWords); 316 int kshellCmd_popenv(const char *pszCmd, PKSHELLWORDS pWords); 317 int kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords); 318 int kshellCmd_write(const char *pszCmd, PKSHELLWORDS pWords); 319 int kshellCmd_ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords); 84 320 85 321 … … 165 401 } aCmds[] = 166 402 { 167 {"copy", MAX_WORDS, kshellCmdcopy}, 168 {"copytree", 3, kshellCmdcopytree}, 169 {"rm", MAX_WORDS, kshellCmdrm}, 170 {"rmtree", MAX_WORDS, kshellCmdrmtree}, 171 {"chdir", 2, kshellCmdchdir}, 172 {"mkdir", MAX_WORDS, kshellCmdmkdir}, 173 {"rmdir", MAX_WORDS, kshellCmdrmdir}, 174 {"set", 1, kshellCmdset}, 175 {"unset", MAX_WORDS, kshellCmdunset}, 176 {"pushenv", MAX_WORDS, kshellCmdpushenv}, 177 {"popenv", 1, kshellCmdpopenv}, 178 {"echo", 2, kshellCmdecho}, 179 {"write", 2, kshellCmdwrite}, 403 {"copy", MAX_WORDS, kshellCmd_copy}, 404 {"copytree", 3, kshellCmd_copytree}, 405 {"sync", MAX_WORDS, kshellCmd_sync}, 406 {"synctree", 3, kshellCmd_synctree}, 407 {"rm", MAX_WORDS, kshellCmd_rm}, 408 {"rmtree", MAX_WORDS, kshellCmd_rmtree}, 409 {"chdir", 2, kshellCmd_chdir}, 410 {"mkdir", MAX_WORDS, kshellCmd_mkdir}, 411 {"rmdir", MAX_WORDS, kshellCmd_rmdir}, 412 {"set", 1, kshellCmd_set}, 413 {"unset", MAX_WORDS, kshellCmd_unset}, 414 {"pushenv", MAX_WORDS, kshellCmd_pushenv}, 415 {"popenv", 1, kshellCmd_popenv}, 416 {"echo", 2, kshellCmd_echo}, 417 {"write", 2, kshellCmd_write}, 180 418 181 419 /* last entry */ 182 {"", 1, kshellCmd ExecuteProgram}420 {"", 1, kshellCmd_ExecuteProgram} 183 421 }; 184 422 #undef MAX_WORDS … … 256 494 * Parse loop 257 495 */ 258 while (cWords > 0)496 while (cWords-- > 0) 259 497 { 260 498 KSHELLWORD word = {0,0,0,0,0}; 261 499 char chEnd = ' '; 500 char ch; 262 501 263 502 /* … … 270 509 word.pszWordOrg = pszText; 271 510 511 272 512 /* 273 513 * Quoted? 514 * Any possible quote! 274 515 */ 275 if ( *pszText == '"')516 if (KSHELL_QUOTE(*pszText)) 276 517 { 277 pszText++;518 chEnd = *pszText++; 278 519 word.fFlags |= KSWORD_FLAGS_QUOTED; 279 chEnd = '"';280 520 } 521 281 522 282 523 /* 283 524 * Find end of word and look for escape and pattern characters. 525 * We escape by doubling the character, not by slashing! 284 526 */ 285 while ( *pszText != '\0' && *pszText != chEnd)527 while ((ch = *pszText) != '\0' && (ch != chEnd || pszText[1] == chEnd)) 286 528 { 287 if ( *pszText == '\\')529 if (ch == pszText[1] && KSHELL_ESCAPABLE(ch)) 288 530 { 289 531 word.fFlags |= KSWORD_FLAGS_ESCAPE; 290 532 pszText++; 291 533 } 292 if ( *pszText == '*' || *pszText == '?')534 if (KSHELL_WILDCHAR(ch)) 293 535 word.fFlags |= KSWORD_FLAGS_PATTERN; 294 536 pszText++; … … 298 540 word.cchWordOrg = pszText - word.pszWordOrg; 299 541 542 300 543 /* 301 * Make a copy of the word and unescape (if required).544 * Make a copy of the word and unescape (if needed). 302 545 */ 303 546 word.pszWord = malloc(word.cchWordOrg + 1); … … 315 558 while (cch) 316 559 { 317 if (*pszSrc == '\\') 560 char ch; 561 if ((ch = *pszSrc) == pszSrc[1] && KSHELL_ESCAPABLE(ch)) 318 562 pszSrc++; 319 *pszTrg++ = *pszSrc++; 563 *pszTrg++ = ch; 564 pszSrc++; 320 565 } 321 566 word.cchWord = pszTrg - word.pszWord; … … 390 635 391 636 /** 637 * Display an syntax message. 638 * @returns KSHELL_ERROR_SYNTAX_ERROR 639 * @param pszCmd The command name. 640 * @param pszMessage Message text. 641 */ 642 int kshellSyntaxError(const char *pszCmd, const char *pszMessage) 643 { 644 fflush(stdout); 645 fprintf(stderr, "Syntax error while executing command '%s': %s\n", pszCmd, pszMessage); 646 return KSHELL_ERROR_SYNTAX_ERROR; 647 } 648 649 650 /** 651 * Display an generic message. 652 * @returns KSHELL_ERROR_SYNTAX_ERROR 653 * @param pszCmd The command name. 654 * @param pszMessage Message text. 655 */ 656 int kshellError(const char *pszCmd, const char *pszMessage) 657 { 658 fflush(stdout); 659 fprintf(stderr, "Error while executing command '%s': %s\n", pszCmd, pszMessage); 660 return -1; 661 } 662 663 664 /** 392 665 * Execute program. 393 666 * … … 399 672 * @param pWords Pointer to 1st word in pszCmd. 400 673 */ 401 int kshellCmd ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords)674 int kshellCmd_ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords) 402 675 { 403 676 return -1; … … 413 686 414 687 415 int kshellCmdcopy(const char *pszCmd, PKSHELLWORDS pWords) 416 { 417 return -1; 418 } 419 420 421 int kshellCmdcopytree(const char *pszCmd, PKSHELLWORDS pWords) 422 { 423 return -1; 424 } 425 426 427 int kshellCmdrm(const char *pszCmd, PKSHELLWORDS pWords) 428 { 429 return -1; 430 } 431 432 433 int kshellCmdrmtree(const char *pszCmd, PKSHELLWORDS pWords) 434 { 435 return -1; 436 } 437 438 439 int kshellCmdchdir(const char *pszCmd, PKSHELLWORDS pWords) 440 { 441 return -1; 442 } 443 444 445 int kshellCmdmkdir(const char *pszCmd, PKSHELLWORDS pWords) 446 { 447 return -1; 448 } 449 450 451 int kshellCmdrmdir(const char *pszCmd, PKSHELLWORDS pWords) 452 { 453 return -1; 454 } 455 456 457 int kshellCmdset(const char *pszCmd, PKSHELLWORDS pWords) 458 { 459 return -1; 460 } 461 462 463 int kshellCmdunset(const char *pszCmd, PKSHELLWORDS pWords) 464 { 465 return -1; 466 } 467 468 469 int kshellCmdpushenv(const char *pszCmd, PKSHELLWORDS pWords) 470 { 471 return -1; 472 } 473 474 475 int kshellCmdpopenv(const char *pszCmd, PKSHELLWORDS pWords) 476 { 477 return -1; 478 } 479 480 481 int kshellCmdecho(const char *pszCmd, PKSHELLWORDS pWords) 482 { 483 return -1; 484 } 485 486 487 int kshellCmdwrite(const char *pszCmd, PKSHELLWORDS pWords) 488 { 489 return -1; 490 } 491 688 int kshellCmd_copy(const char *pszCmd, PKSHELLWORDS pWords) 689 { 690 return -1; 691 } 692 693 694 int kshellCmd_copytree(const char *pszCmd, PKSHELLWORDS pWords) 695 { 696 return -1; 697 } 698 699 700 int kshellCmd_sync(const char *pszCmd, PKSHELLWORDS pWords) 701 { 702 return -1; 703 } 704 705 706 int kshellCmd_synctree(const char *pszCmd, PKSHELLWORDS pWords) 707 { 708 return -1; 709 } 710 711 712 int kshellCmd_rm(const char *pszCmd, PKSHELLWORDS pWords) 713 { 714 return -1; 715 } 716 717 718 int kshellCmd_rmtree(const char *pszCmd, PKSHELLWORDS pWords) 719 { 720 return -1; 721 } 722 723 724 int kshellCmd_chdir(const char *pszCmd, PKSHELLWORDS pWords) 725 { 726 return -1; 727 } 728 729 730 int kshellCmd_mkdir(const char *pszCmd, PKSHELLWORDS pWords) 731 { 732 return -1; 733 } 734 735 736 int kshellCmd_rmdir(const char *pszCmd, PKSHELLWORDS pWords) 737 { 738 return -1; 739 } 740 741 742 int kshellCmd_set(const char *pszCmd, PKSHELLWORDS pWords) 743 { 744 return -1; 745 } 746 747 748 int kshellCmd_unset(const char *pszCmd, PKSHELLWORDS pWords) 749 { 750 return -1; 751 } 752 753 754 int kshellCmd_pushenv(const char *pszCmd, PKSHELLWORDS pWords) 755 { 756 return -1; 757 } 758 759 760 int kshellCmd_popenv(const char *pszCmd, PKSHELLWORDS pWords) 761 { 762 return -1; 763 } 764 765 766 /** @subsubsection echo 767 * Prints a message to stdout. 768 * 769 * <b>Syntax: echo <level> <message> 770 * 771 * Level is verbosity level of the message. This is compared with the 772 * KBUILD_MSG_LEVEL environment variable. The message is suppressed if the 773 * level is lower that KBUILD_MSG_LEVEL. 774 * 775 * The message is printed word for word normalize with a single space between 776 * the words. It's therefore a good thing to quote the message. 777 * 778 * The message can be empty. Then a blank line will be printed. 779 */ 780 int kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords) 781 { 782 int rc = KSHELL_ERROR_SYNTAX_ERROR; 783 784 /* 785 * Get the message level from the message. 786 */ 787 if (pWords->cWords >= 2) 788 { 789 unsigned uMsgLevel = kStrToUnsigned(pWords->aWords[1].pszWord, -2); 790 if (uMsgLevel != -2) 791 { 792 if (uMsgLevel <= kEnvGetUnsigned("KBUILD_MSG_LEVEL", 0)) 793 { 794 /* output all the words forcing one space separation */ 795 pWords = kshellWordsParse(pszCmd, -1, pWords); 796 if (pWords) 797 { 798 int i; 799 for (i = 2; i < pWords->cWords; i++) 800 fwrite(pWords->aWords[i].pszWord, pWords->aWords[i].cchWord, 1, stdout); 801 } 802 803 /* new line */ 804 fputc('\n', stdout); 805 fflush(stdout); 806 } 807 } 808 else 809 kshellSyntaxError("echo", "invalid message level!"); 810 } 811 else 812 kshellSyntaxError("echo", "requires at least one argument!"); 813 814 return -1; 815 } 816 817 818 int kshellCmd_write(const char *pszCmd, PKSHELLWORDS pWords) 819 { 820 return -1; 821 } 822 823 824 -
trunk/src/kShell/makefile
r21 r23 1 1 # $Id$ 2 3 #CC = icc /Q /Ti+ /I../kLib/Generic/include 4 CC = icc /Q /Ti+ -DOS2 -D__i386__ -DDEBUG /Ig:/ktaskmgr/tree/Generic/include 5 CC = icc /Q /Ti+ /O /Oi+ -DOS2 -D__i386__ -DDEBUG /Ig:/ktaskmgr/tree/Generic/include 6 2 7 3 8 all: kShellMain.exe \ … … 5 10 6 11 kShellMain.exe: kShellMain.c kShell.c kShell.h 7 icc /Q /Ti+kShellmain.c kShell.c12 $(CC) kShellmain.c kShell.c 8 13 9 14 kShellMain.obj: kShellMain.c kShell.h 10 icc /Q /c /Ti+kShellMain.c15 $(CC) /c kShellMain.c 11 16 12 17 kShell.obj: kShell.c kShell.h 13 icc /Q /c /Ti+kShell.c18 $(CC) /c kShell.c 14 19 15 20 kShell.lib:
Note:
See TracChangeset
for help on using the changeset viewer.