Changeset 23 for trunk/src/kShell


Ignore:
Timestamp:
Nov 22, 2002, 5:00:46 AM (23 years ago)
Author:
bird
Message:

working on it...

Location:
trunk/src/kShell
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kShell/kShell.c

    r19 r23  
    2323 *
    2424 */
     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
    25223
    26224/*******************************************************************************
     
    33231#define KSHELL_MAX_COMMAND      4096
    34232
     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
    35258/*******************************************************************************
    36259*   Header Files                                                               *
    37260*******************************************************************************/
    38261#include "kShell.h"
     262#include <kLib/kLib.h>
     263#include <kLib/kString.h>
     264
    39265#include <string.h>
    40266#include <stdlib.h>
     
    63289
    64290/*******************************************************************************
     291*   Global Variables                                                           *
     292*******************************************************************************/
     293static const char *pszkshellCurDir = NULL;
     294
     295/*******************************************************************************
    65296*   Internal Functions                                                         *
    66297*******************************************************************************/
     
    68299void            kshellWordsDestroy(PKSHELLWORDS pWords);
    69300
    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);
     301int             kshellSyntaxError(const char *pszCmd, const char *pszMessage);
     302int             kshellError(const char *pszCmd, const char *pszMessage);
     303
     304int             kshellCmd_copy(const char *pszCmd, PKSHELLWORDS pWords);
     305int             kshellCmd_copytree(const char *pszCmd, PKSHELLWORDS pWords);
     306int             kshellCmd_sync(const char *pszCmd, PKSHELLWORDS pWords);
     307int             kshellCmd_synctree(const char *pszCmd, PKSHELLWORDS pWords);
     308int             kshellCmd_rm(const char *pszCmd, PKSHELLWORDS pWords);
     309int             kshellCmd_rmtree(const char *pszCmd, PKSHELLWORDS pWords);
     310int             kshellCmd_chdir(const char *pszCmd, PKSHELLWORDS pWords);
     311int             kshellCmd_mkdir(const char *pszCmd, PKSHELLWORDS pWords);
     312int             kshellCmd_rmdir(const char *pszCmd, PKSHELLWORDS pWords);
     313int             kshellCmd_set(const char *pszCmd, PKSHELLWORDS pWords);
     314int             kshellCmd_unset(const char *pszCmd, PKSHELLWORDS pWords);
     315int             kshellCmd_pushenv(const char *pszCmd, PKSHELLWORDS pWords);
     316int             kshellCmd_popenv(const char *pszCmd, PKSHELLWORDS pWords);
     317int             kshellCmd_echo(const char *pszCmd, PKSHELLWORDS pWords);
     318int             kshellCmd_write(const char *pszCmd, PKSHELLWORDS pWords);
     319int             kshellCmd_ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords);
    84320
    85321
     
    165401    } aCmds[] =
    166402    {
    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},
    180418
    181419        /* last entry */
    182         {"",            1,          kshellCmdExecuteProgram}
     420        {"",            1,          kshellCmd_ExecuteProgram}
    183421    };
    184422#undef MAX_WORDS
     
    256494     * Parse loop
    257495     */
    258     while (cWords > 0)
     496    while (cWords-- > 0)
    259497    {
    260498        KSHELLWORD  word = {0,0,0,0,0};
    261499        char        chEnd = ' ';
     500        char        ch;
    262501
    263502        /*
     
    270509        word.pszWordOrg = pszText;
    271510
     511
    272512        /*
    273513         * Quoted?
     514         * Any possible quote!
    274515         */
    275         if (*pszText == '"')
     516        if (KSHELL_QUOTE(*pszText))
    276517        {
    277             pszText++;
     518            chEnd = *pszText++;
    278519            word.fFlags |= KSWORD_FLAGS_QUOTED;
    279             chEnd = '"';
    280520        }
     521
    281522
    282523        /*
    283524         * Find end of word and look for escape and pattern characters.
     525         * We escape by doubling the character, not by slashing!
    284526         */
    285         while (*pszText != '\0' && *pszText != chEnd)
     527        while ((ch = *pszText) != '\0' && (ch != chEnd || pszText[1] == chEnd))
    286528        {
    287             if (*pszText == '\\')
     529            if (ch == pszText[1] && KSHELL_ESCAPABLE(ch))
    288530            {
    289531                word.fFlags |= KSWORD_FLAGS_ESCAPE;
    290532                pszText++;
    291533            }
    292             if (*pszText == '*' || *pszText == '?')
     534            if (KSHELL_WILDCHAR(ch))
    293535                word.fFlags |= KSWORD_FLAGS_PATTERN;
    294536            pszText++;
     
    298540        word.cchWordOrg = pszText - word.pszWordOrg;
    299541
     542
    300543        /*
    301          * Make a copy of the word and unescape (if required).
     544         * Make a copy of the word and unescape (if needed).
    302545         */
    303546        word.pszWord = malloc(word.cchWordOrg + 1);
     
    315558            while (cch)
    316559            {
    317                 if (*pszSrc == '\\')
     560                char ch;
     561                if ((ch = *pszSrc) == pszSrc[1] && KSHELL_ESCAPABLE(ch))
    318562                    pszSrc++;
    319                 *pszTrg++ = *pszSrc++;
     563                *pszTrg++ = ch;
     564                pszSrc++;
    320565            }
    321566            word.cchWord = pszTrg - word.pszWord;
     
    390635
    391636/**
     637 * Display an syntax message.
     638 * @returns KSHELL_ERROR_SYNTAX_ERROR
     639 * @param   pszCmd      The command name.
     640 * @param   pszMessage  Message text.
     641 */
     642int             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 */
     656int             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/**
    392665 * Execute program.
    393666 *
     
    399672 * @param   pWords  Pointer to 1st word in pszCmd.
    400673 */
    401 int             kshellCmdExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords)
     674int             kshellCmd_ExecuteProgram(const char *pszCmd, PKSHELLWORDS pWords)
    402675{
    403676    return -1;
     
    413686
    414687
    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 
     688int             kshellCmd_copy(const char *pszCmd, PKSHELLWORDS pWords)
     689{
     690    return -1;
     691}
     692
     693
     694int             kshellCmd_copytree(const char *pszCmd, PKSHELLWORDS pWords)
     695{
     696    return -1;
     697}
     698
     699
     700int             kshellCmd_sync(const char *pszCmd, PKSHELLWORDS pWords)
     701{
     702    return -1;
     703}
     704
     705
     706int             kshellCmd_synctree(const char *pszCmd, PKSHELLWORDS pWords)
     707{
     708    return -1;
     709}
     710
     711
     712int             kshellCmd_rm(const char *pszCmd, PKSHELLWORDS pWords)
     713{
     714    return -1;
     715}
     716
     717
     718int             kshellCmd_rmtree(const char *pszCmd, PKSHELLWORDS pWords)
     719{
     720    return -1;
     721}
     722
     723
     724int             kshellCmd_chdir(const char *pszCmd, PKSHELLWORDS pWords)
     725{
     726    return -1;
     727}
     728
     729
     730int             kshellCmd_mkdir(const char *pszCmd, PKSHELLWORDS pWords)
     731{
     732    return -1;
     733}
     734
     735
     736int             kshellCmd_rmdir(const char *pszCmd, PKSHELLWORDS pWords)
     737{
     738    return -1;
     739}
     740
     741
     742int             kshellCmd_set(const char *pszCmd, PKSHELLWORDS pWords)
     743{
     744    return -1;
     745}
     746
     747
     748int             kshellCmd_unset(const char *pszCmd, PKSHELLWORDS pWords)
     749{
     750    return -1;
     751}
     752
     753
     754int             kshellCmd_pushenv(const char *pszCmd, PKSHELLWORDS pWords)
     755{
     756    return -1;
     757}
     758
     759
     760int             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 */
     780int             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
     818int             kshellCmd_write(const char *pszCmd, PKSHELLWORDS pWords)
     819{
     820    return -1;
     821}
     822
     823
     824
  • trunk/src/kShell/makefile

    r21 r23  
    11# $Id$
     2
     3#CC = icc /Q /Ti+ /I../kLib/Generic/include
     4CC = icc /Q /Ti+ -DOS2 -D__i386__ -DDEBUG /Ig:/ktaskmgr/tree/Generic/include
     5CC = icc /Q /Ti+ /O /Oi+ -DOS2 -D__i386__ -DDEBUG /Ig:/ktaskmgr/tree/Generic/include
     6
    27
    38all: kShellMain.exe \
     
    510                       
    611kShellMain.exe: kShellMain.c kShell.c kShell.h
    7         icc /Q /Ti+ kShellmain.c kShell.c
     12        $(CC) kShellmain.c kShell.c
    813       
    914kShellMain.obj: kShellMain.c kShell.h
    10         icc /Q /c /Ti+ kShellMain.c
     15        $(CC) /c kShellMain.c
    1116
    1217kShell.obj: kShell.c kShell.h
    13         icc /Q /c /Ti+ kShell.c
     18        $(CC) /c kShell.c
    1419       
    1520kShell.lib:
Note: See TracChangeset for help on using the changeset viewer.