Changeset 407 for trunk/user/ksh/ksh.c


Ignore:
Timestamp:
Nov 7, 2017, 3:08:12 PM (5 years ago)
Author:
alain
Message:

First implementation of fork/exec.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/user/ksh/ksh.c

    r230 r407  
    1 /*
    2  * Authors: Clément Guérin and Alain Greiner (2015)
    3  */
    4 
     1///////////////////////////////////////////////////////////////////////////////
     2// File   :  ksh.c
     3// Date   :  October 2017
     4// Author :  Alain Greiner
     5///////////////////////////////////////////////////////////////////////////////
     6// This single thread application implement a simple shell for ALMOS-MKH.
     7///////////////////////////////////////////////////////////////////////////////
     8
     9#include <nostdio.h>
    510#include <stdio.h>
    611#include <stdlib.h>
    7 #include <unistd.h>
    812#include <string.h>
    9 #include <fcntl.h>
    10 #include <dirent.h>
    11 #include <sys/stat.h>
    12 #include <sys/mman.h>
    13 #include <sys/wait.h>
    14 #include <signal.h>
    15 #include <errno.h>
    16 
    17 #define MAX_SIZE        (128)  // max number of characters in one command
    18 #define LOG_DEPTH   (128)  // max number of commands in log
    19 #define MAX_ARGS        (32)   // max number of arguments in a command
    20 #define FIFO_SIZE   (1024) // FIFO depth for recursive ls
    21 
    22 #define __unused(a)     (void)a
    23 
    24 extern char **environ;
     13
     14#define CMD_MAX_SIZE   (256)    // max number of characters in one command
     15#define LOG_DEPTH      (256)    // max number of registered commands
     16#define MAX_ARGS           (32)     // max number of arguments in a command
     17#define FIFO_SIZE      (1024)   // FIFO depth for recursive ls
     18
     19////////////////////////////////////////////////////////////////////////////////
     20//         Structures
     21////////////////////////////////////////////////////////////////////////////////
     22
     23// one entry in the registered commands array
     24typedef struct log_entry_s
     25{
     26        char          buf[CMD_MAX_SIZE];
     27        unsigned int  count;
     28}
     29log_entry_t;
     30
     31// one entry in the supported command types array
     32typedef struct ksh_cmd_s
     33{
     34        char * name;
     35        char * desc;
     36        void   (*fn)( int , char ** );
     37}
     38ksh_cmd_t;
     39
    2540
    2641////////////////////////////////////////////////////////////////////////////////
     
    2843////////////////////////////////////////////////////////////////////////////////
    2944
    30 struct {
    31         char buf[MAX_SIZE];
    32         size_t count;
    33 } log_entries[LOG_DEPTH];
    34 
    35 size_t ptw; // write pointer in log
    36 size_t ptr; // read pointer in log
    37 
    38 struct command_t {
    39         char *name;
    40         char *desc;
    41         void (*fn)(int, char **);
    42 };
    43 
    44 struct command_t cmd[];
     45ksh_cmd_t       cmd[];                    // array of supported commands
     46
     47log_entry_t     log_entries[LOG_DEPTH];   // array of registered commands
     48
     49unsigned int    ptw;                      // write pointer in log_entries[]
     50unsigned int    ptr;                      // read pointer in log_entries[]
    4551
    4652////////////////////////////////////////////////////////////////////////////////
     
    4854////////////////////////////////////////////////////////////////////////////////
    4955
    50 static void cmd_cat(int argc, char **argv)
    51 {
    52         char *path, *buf = NULL;
    53         struct stat st;
    54         size_t size;
    55         int fd;
    56 
    57         if (argc != 2) {
     56/////////////////////////////////////////////
     57static void cmd_cat( int argc , char **argv )
     58{
     59        char         * path;
     60
     61        if (argc != 2)
     62    {
    5863                printf("usage: cat pathname\n");
    5964                return;
    6065        }
     66
    6167        path = argv[1];
    6268
    63         /* open the file */
    64         fd = open(path, O_RDONLY, 0);
    65         if (fd < 0) {
     69    printf("error: not implemented yet\n");
     70
     71/*
     72        // open the file
     73        fd = open( path , O_RDONLY , 0 );
     74        if (fd < 0)
     75    {
    6676                printf("error: cannot open %s\n", path);
    6777                goto exit;
    6878        }
    6979
    70         /* get file size */
    71         if (stat(path, &st) == -1) {
     80        // get file size
     81        if (stat(path, &st) == -1)
     82    {
    7283                printf("error: cannot stat %s\n", path);
    7384                goto exit;
     
    7990        size = st.st_size;
    8091
    81         /* mmap the file */
     92        // mmap the file
    8293        buf = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
    8394        if (buf == NULL || buf == (char *)-1) {
     
    8697        }
    8798
    88         /* set terminating '0' XXX */
     99        // set terminating '0' XXX
    89100        buf[size-1] = 0;
    90101
    91         /* display the file content */
     102        // display the file content
    92103        printf("%s", buf);
    93104
    94105exit:
    95         if (buf != NULL)
    96                 munmap(buf, size);
    97         if (fd >= 0)
    98                 close(fd);
    99 }
    100 
     106        if (buf != NULL) munmap(buf, size);
     107        if (fd >= 0) close(fd);
     108*/
     109
     110}   // end cmd_cat()
     111
     112////////////////////////////////////////////
     113static void cmd_cd( int argc , char **argv )
     114{
     115        char * path;
     116
     117        if (argc != 2)
     118    {
     119                printf("usage: cd pathname\n");
     120                return;
     121        }
     122
     123        path = argv[1];
     124
     125    printf("error: not implemented yet\n");
     126/*
     127        path = argv[1];
     128
     129        if (chdir(path) == -1)
     130    {
     131                printf("error: cannot cd to %s\n", path);
     132        }
     133*/
     134
     135}   // end cmd_cd()
     136
     137/////////////////////////////////////////
    101138static void cmd_cp(int argc, char **argv)
    102139{
    103         int src_fd = -1, dst_fd = -1;
    104         char *srcpath, *dstpath;
    105         struct stat st;
    106         size_t size, i;
    107         char buf[1024];
    108 
    109         if (argc != 3) {
     140//      int src_fd = -1, dst_fd = -1;
     141//      char *srcpath, *dstpath;
     142//      struct stat st;
     143//      size_t size, i;
     144//      char buf[1024];
     145
     146        if (argc != 3)
     147    {
    110148                printf("usage: cp src_pathname dst_pathname\n");
    111149                return;
    112150        }
    113151
     152    printf("error: not implemented yet\n");
     153
     154/*
    114155        srcpath = argv[1];
    115156        dstpath = argv[2];
    116157
    117         /* open the src file */
     158        // open the src file
    118159        src_fd = open(srcpath, O_RDONLY, 0);
    119160        if (src_fd < 0) {
     
    122163        }
    123164
    124         /* get file size */
     165        // get file size
    125166        if (stat(srcpath, &st) == -1) {
    126167                printf("error: cannot stat %s\n", srcpath);
     
    133174        size = st.st_size;
    134175
    135         /* open the dst file */
     176        // open the dst file
    136177        dst_fd = open(dstpath, O_CREAT|O_TRUNC|O_RDWR, 0);
    137178        if (dst_fd < 0) {
     
    155196                ssize_t ret;
    156197
    157                 /* read the source */
     198                // read the source
    158199                ret = read(src_fd, buf, rlen);
    159200                if (ret == -1) {
     
    163204                rlen = (size_t)ret;
    164205
    165                 /* write to the destination */
     206                // write to the destination
    166207                ret = write(dst_fd, buf, rlen);
    167208                if (ret == -1) {
     
    171212                wlen = (size_t)ret;
    172213
    173                 /* check */
     214                // check
    174215                if (wlen != rlen) {
    175216                        printf("error: cannot write on device\n");
     
    181222
    182223exit:
    183         if (src_fd >= 0)
    184                 close(src_fd);
    185         if (dst_fd >= 0)
    186                 close(dst_fd);
    187 }
    188 
    189 static void cmd_exec(int argc, char **argv)
    190 {
    191         pid_t pid, wpid;
    192         int status;
    193         char *path;
    194 
    195         if (argc != 2) {
    196                 printf("usage: %s prog\n", argv[0]);
    197                 return;
    198         }
    199 
    200         path = argv[1];
    201         argv++;
    202 
     224        if (src_fd >= 0) close(src_fd);
     225        if (dst_fd >= 0) close(dst_fd);
     226*/
     227
     228}   // end cmd_cp()
     229
     230//////////////////////////////////////////////
     231static void cmd_help( int argc , char **argv )
     232{
     233        unsigned int i;
     234
     235        if (argc != 1)
     236    {
     237                printf("usage: %s\n", argv[0]);
     238                return;
     239        }
     240
     241        printf("available commands:\n");
     242        for (i = 0 ; cmd[i].name ; i++)
     243    {
     244                printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc);
     245        }
     246}   // end cmd_help()
     247
     248//////////////////////////////////////////////
     249static void cmd_kill( int argc , char **argv )
     250{
     251        unsigned int pid;
     252
     253        if (argc != 2)
     254    {
     255                printf("usage: %s pid\n", argv[0]);
     256                return;
     257        }
     258
     259        pid = atoi(argv[1]);
     260
     261        if( kill( pid , 9 ) )   // TODO replace 9 by SIGKILL
     262    {
     263                printf("error: unable to kill process %x\n", pid );
     264        }
     265}   // end cmd_kill()
     266
     267//////////////////////////////////////////////
     268static void cmd_load( int argc , char **argv )
     269{
     270        unsigned int   pid;
     271    unsigned int   error;
     272        char         * pathname;
     273
     274        if (argc != 2)
     275    {
     276                printf("usage: %s pathname \n", argv[0] );
     277                return;
     278        }
     279
     280        pathname = argv[1];
     281
     282    // fork system call
    203283        pid = fork();
    204         if (pid == 0) {
    205                 /* child process */
    206                 if (execve(path, argv, environ) == -1) {
    207                         printf("error: unable to execve %s\n", path);
    208                 }
    209                 exit(EXIT_FAILURE);
    210         } else if (pid < 0) {
    211                 /* error forking */
    212                 printf("error: unable to fork\n");
    213         } else {
    214                 /* parent process */
    215                 do {
    216                         wpid = waitpid(pid, &status, WUNTRACED);
    217                 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
    218         }
    219 }
    220 
    221 static void cmd_help(int argc, char **argv)
    222 {
    223         size_t i;
    224         __unused(argc);
    225         __unused(argv);
    226         printf("available commands:\n");
    227         for (i = 0; cmd[i].name; i++) {
    228                 printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc);
    229         }
    230 }
    231 
    232 static void cmd_kill(int argc, char **argv)
    233 {
    234         pid_t pid;
    235 
    236         if (argc != 2) {
    237                 printf("usage: %s pid\n", argv[0]);
    238                 return;
    239         }
    240 
    241         pid = (pid_t)atoi(argv[1]);
    242 
    243         if (kill(pid, SIGKILL) == -1) {
    244                 printf("error: unable to kill %d\n", (int)pid);
    245         }
    246 }
    247 
    248 static void cmd_log(int argc, char **argv)
    249 {
    250         size_t i;
    251         __unused(argc);
    252         __unused(argv);
     284
     285    if (pid == 0)  // it is the child process
     286    {
     287
     288printf("\n[KSH_DBG] process %x before exec\n", getpid() );
     289
     290        // exec system call
     291        error = exec( pathname , NULL , NULL );
     292
     293printf("\n[KSH_DBG] process %x after exec / error = %d\n", getpid() , error );
     294
     295        if( error )
     296        {
     297            printf("error: new process unable to exec <%s>\n", pathname );
     298            // TODO exit();
     299        }
     300        }
     301    else if ( pid < 0 )  // it is a failure reported to parent
     302    {
     303        printf("error: unable to fork\n");
     304    }
     305    else                 // it is a success reported to parent
     306    {
     307
     308printf("\n[KSH_DBG] process %x created for <%s>\n", pid, pathname );
     309
     310    }
     311
     312}   // end cmd_load
     313
     314/////////////////////////////////////////////
     315static void cmd_log( int argc , char **argv )
     316{
     317        unsigned int i;
     318
    253319        printf("--- registered commands ---\n");
    254         for (i = 0; i < LOG_DEPTH; i++) {
     320        for (i = 0; i < LOG_DEPTH; i++)
     321    {
    255322                printf(" - %zu\t: %s\n", i, &log_entries[i].buf);
    256323        }
    257324}
    258325
    259 static void cmd_ls(int argc, char **argv)
    260 {
    261     struct dirent *file;
    262         char *path;
    263     DIR *dir;
    264 
    265         if (argc == 1) {
     326////////////////////////////////////////////
     327static void cmd_ls( int argc , char **argv )
     328{
     329        char  * path;
     330
     331//  struct dirent * file;
     332//  DIR *dir;
     333
     334        if (argc == 1)
     335    {
    266336                path = ".";
    267         } else if (argc == 2) {
     337        }
     338    else if (argc == 2)
     339    {
    268340                path = argv[1];
    269         } else {
     341        }
     342    else
     343    {
    270344                printf("usage: ls [path]\n");
    271345                return;
    272346        }
    273347
    274         dir = opendir(path);
     348    printf("error: not implemented yet\n");
     349/*
     350        dir = opendir( path );
    275351        while ((file = readdir(dir)) != NULL)
    276352        {
     
    278354        }
    279355        closedir(dir);
    280 }
    281 
    282 static void cmd_mkdir(int argc, char **argv)
    283 {
    284         char *path;
    285 
    286         if (argc != 2) {
     356*/
     357}
     358
     359///////////////////////////////////////////////
     360static void cmd_mkdir( int argc , char **argv )
     361{
     362        char * pathname;
     363
     364        if (argc != 2)
     365    {
    287366                printf("usage: mkdir pathname\n");
    288367                return;
    289368        }
    290369
    291         path = argv[1];
    292 
    293         if (mkdir(path, 0700) == -1) {
     370    pathname = argv[1];
     371
     372    printf("error: not implemented yet\n");
     373/*
     374        if ( mkdir( path, 0x700) == -1 )
     375    {
    294376                printf("error: cannot create directory %s\n", path);
    295377        }
    296 }
    297 
    298 static void cmd_mv(int argc, char **argv)
    299 {
    300 #if 0
     378*/
     379}
     380
     381////////////////////////////////////////////
     382static void cmd_mv( int argc , char **argv )
     383{
     384
    301385        if (argc < 3)
    302386        {
     
    305389        }
    306390
     391    printf("error: not implemented yet\n");
     392   
     393/*
    307394        int ret = giet_fat_rename(argv[1], argv[2]);
    308395        if (ret < 0)
     
    310397                printf("error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
    311398        }
    312 #endif
    313 }
    314 
    315 static void cmd_rm(int argc, char **argv)
    316 {
    317         char *path;
    318 
    319         if (argc != 2) {
     399*/
     400
     401}
     402
     403/////////////////////////////////////////////
     404static void cmd_pwd( int argc , char **argv )
     405{
     406        char buf[1024];
     407
     408        if (argc != 1)
     409    {
     410                printf("usage: pwd\n");
     411                return;
     412        }
     413
     414        if ( getcwd( buf , 1024 ) )
     415    {
     416                printf("error: unable to get current directory\n");
     417        }
     418    else
     419    {
     420                printf("%s\n", buf);
     421        }
     422}
     423
     424////////////////////////////////////////////
     425static void cmd_rm( int argc , char **argv )
     426{
     427        char * pathname;
     428
     429        if (argc != 2)
     430    {
    320431                printf("usage: rm pathname\n");
    321432                return;
    322433        }
    323434
    324         path = argv[1];
    325 
    326         if (remove(path) == -1) {
     435        pathname = argv[1];
     436
     437    printf("error: not implemented yet\n");
     438/*
     439        if (remove(path) == -1)
     440    {
    327441                printf("error: cannot remove %s\n", path);
    328442        }
    329 }
    330 
    331 static void cmd_rmdir(int argc, char **argv)
     443*/
     444
     445}
     446
     447///////////////////////////////////////////////
     448static void cmd_rmdir( int argc , char **argv )
    332449{
    333450        cmd_rm(argc, argv);
    334451}
    335452
    336 static void cmd_cd(int argc, char **argv)
    337 {
    338         char *path;
    339 
    340         if (argc != 2) {
    341                 printf("usage: cd pathname\n");
    342                 return;
    343         }
    344 
    345         path = argv[1];
    346 
    347         if (chdir(path) == -1) {
    348                 printf("error: cannot cd to %s\n", path);
    349         }
    350 }
    351 
    352 static void cmd_pwd(int argc, char **argv)
    353 {
    354         char buf[1024];
    355 
    356         if (argc != 1) {
    357                 printf("usage: pwd\n");
    358                 return;
    359         }
    360 
    361         if (getcwd(buf, 1024) == NULL) {
    362                 printf("error: unable to get current directory\n");
    363         } else {
    364                 printf("%s\n", buf);
    365         }
    366 }
    367 
    368 struct command_t cmd[] =
    369 {
    370         { "cat",    "display file content",                cmd_cat },
    371         { "cd",     "change current directory",            cmd_cd },
    372         { "cp",     "replicate a file in file system",     cmd_cp },
    373         { "exec",   "start an application",                cmd_exec },
    374         { "help",   "list available commands",             cmd_help },
    375         { "kill",   "kill an application (all threads)",   cmd_kill },
    376         { "log",    "list registered commands",            cmd_log },
    377         { "ls",     "list directory entries",              cmd_ls },
     453///////////////////////////////////////////////
     454static void cmd_sched( int argc , char **argv )
     455{
     456    unsigned int cxy;
     457    unsigned int lid;
     458
     459        if (argc != 3)
     460    {
     461                printf("usage: sched cxy lid\n");
     462                return;
     463        }
     464
     465        cxy = atoi(argv[1]);
     466        lid = atoi(argv[2]);
     467
     468    if( get_sched( cxy , lid ) )
     469    {
     470        printf("error: illegal arguments\n");
     471    }
     472}
     473
     474//////////////////////////////////////////////////////////////////
     475// Array of commands
     476//////////////////////////////////////////////////////////////////
     477
     478ksh_cmd_t cmd[] =
     479{
     480        { "cat",    "display file content",                cmd_cat   },
     481        { "cd",     "change current directory",            cmd_cd    },
     482        { "cp",     "replicate a file in file system",     cmd_cp    },
     483        { "load",   "load an user application",            cmd_load  },
     484        { "help",   "list available commands",             cmd_help  },
     485        { "kill",   "kill an application (all threads)",   cmd_kill  },
     486        { "log",    "list registered commands",            cmd_log   },
     487        { "ls",     "list directory entries",              cmd_ls    },
    378488        { "mkdir",  "create a new directory",              cmd_mkdir },
    379         { "mv",     "move a file in file system",          cmd_mv },
    380         { "pwd",    "print current working directory",     cmd_pwd },
    381         { "rm",     "remove a file from file system",      cmd_rm },
     489        { "mv",     "move a file in file system",          cmd_mv    },
     490        { "pwd",    "print current working directory",     cmd_pwd   },
     491        { "rm",     "remove a file from file system",      cmd_rm    },
    382492        { "rmdir",  "remove a directory from file system", cmd_rmdir },
    383         { NULL,     NULL,                                                                  NULL }
     493    { "sched",  "display scheduler state",             cmd_sched },
     494        { NULL,     NULL,                                                                  NULL      }
    384495};
    385496
    386 ///////////////////////////////////////////////////////////////////
    387 // This function analyses one command (with arguments)
    388 ///////////////////////////////////////////////////////////////////
     497////////////////////////////////////////////////////////////////////////////////////
     498// This function analyses one command (with arguments), execute it, and return.
     499////////////////////////////////////////////////////////////////////////////////////
    389500static void parse(char *buf)
    390501{
     
    395506
    396507        // build argc/argv
    397         for (i = 0; i < len; i++) {
    398                 if (buf[i] == ' ') {
     508        for (i = 0; i < len; i++)
     509    {
     510                if (buf[i] == ' ')
     511        {
    399512                        buf[i] = '\0';
    400                 } else if (i == 0 || buf[i - 1] == '\0') {
    401                         if (argc < MAX_ARGS) {
     513                }
     514        else if (i == 0 || buf[i - 1] == '\0')
     515        {
     516                        if (argc < MAX_ARGS)
     517            {
    402518                                argv[argc] = &buf[i];
    403519                                argc++;
     
    406522        }
    407523
    408         if (argc > 0) {
     524        if (argc > 0)
     525    {
    409526                int found = 0;
    410527
    411528                argv[argc] = NULL;
    412529
    413                 // try to match typed command with built-ins
    414                 for (i = 0; cmd[i].name; i++) {
    415                         if (strcmp(argv[0], cmd[i].name) == 0) {
     530                // try to match typed command
     531                for (i = 0; cmd[i].name; i++)
     532        {
     533                        if (strcmp(argv[0], cmd[i].name) == 0)
     534            {
    416535                                cmd[i].fn(argc, argv);
    417536                                found = 1;
     
    420539                }
    421540
    422                 if (!found) {
     541                if (!found)
     542        {
    423543                        printf("\n  undefined command %s\n", argv[0]);
    424544                }
     
    426546}
    427547
    428 int main(int argc, char *argv[])
    429 {
    430         char c;                                                   // read character
    431         char buf[MAX_SIZE];                               // buffer for one command
    432         size_t count = 0;                                         // pointer in buf
    433         size_t i, j;                                              // indexes for loops
    434         __unused(argc);
    435         __unused(argv);
    436 
    437         enum fsm_states {
     548///////////////////////////////////
     549int main( int argc , char *argv[] )
     550{
     551        char         c;                                           // read character
     552        char         buf[CMD_MAX_SIZE];           // buffer for one command
     553        unsigned int count = 0;                           // pointer in buf
     554        unsigned int i;                                           // index for loops
     555
     556        enum fsm_states
     557    {
    438558                NORMAL,
    439559                ESCAPE,
     
    441561        };
    442562
    443         memset(&log_entries, 0, sizeof(log_entries));
    444         ptw = 0;
    445         ptr = 0;
     563    // log buffer initialisation
     564        memset( &log_entries , 0, sizeof(log_entries));
     565        ptw   = 0;
     566        ptr   = 0;
    446567
    447568        printf( "~~~ shell ~~~\n\n" );
    448569
    449570        // command buffer initialisation
    450         memset(buf, 0x20, sizeof(buf));
     571        memset( buf, 0x20 , sizeof(buf) );
    451572        count = 0;
    452573
     
    460581        // - ESC [ C : right arrow
    461582        // - ESC [ D : left arrow
    462         // The thee states have the following semantic:
     583        // The three states have the following semantic:
    463584        // - NORMAL : no (ESC) character has been found
    464585        // - ESCAPE : the character (ESC) has been found
     
    466587        unsigned int state = NORMAL;
    467588
     589// @@@
     590parse("load /bin/user/sort.elf");
     591// @@@
     592   
    468593        while (1)
    469594        {
    470                 /*
    471                  * Certainly not a good idea to use getchar. The escape sequences won't
    472                  * be handled correctly.
    473                  */
    474                 c = getchar();
     595                c = (char)getchar();
     596
     597        if( c == 0 ) continue;
    475598
    476599                switch (state)
Note: See TracChangeset for help on using the changeset viewer.