Creating A Shell: Difference between revisions
[unchecked revision] | [unchecked revision] |
m Who says output/input? |
Use <source> to represent code snippets |
||
Line 12: | Line 12: | ||
First we need to make a file, shell.c, this file will contain all our functions and shell managers. The first function we need to write is our initialization function then our actual shell function. |
First we need to make a file, shell.c, this file will contain all our functions and shell managers. The first function we need to write is our initialization function then our actual shell function. |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
void init_shell() |
|||
void init_shell() |
|||
{ |
|||
{ |
|||
} |
|||
} |
|||
void shell() |
|||
{ |
|||
{ |
|||
} |
|||
</source> |
|||
} |
|||
Now you need to add "init_shell()" to your setup routine in your kernel.c file or whatever you named it, followed by a while loop running shell until the boolean "exit_status" is true. |
Now you need to add "init_shell()" to your setup routine in your kernel.c file or whatever you named it, followed by a while loop running shell until the boolean "exit_status" is true. |
||
Line 27: | Line 27: | ||
Ok, now we need to write a few things. The first is command table, or a way to store our commands. I do this with a structure as follows: |
Ok, now we need to write a few things. The first is command table, or a way to store our commands. I do this with a structure as follows: |
||
<source lang="c"> |
|||
/* shell.h */ |
|||
/* shell.h */ |
|||
#define MAX_COMMANDS 100 |
|||
#define MAX_COMMANDS 100 |
|||
typedef struct |
|||
typedef struct |
|||
{ |
|||
{ |
|||
char *name; |
|||
char *name; |
|||
char *description; |
|||
void *function; |
|||
} command_table_t; |
|||
</source> |
|||
Now we have a way to store commands, but how do we use this? Well lets add a few variables to shell.c: |
Now we have a way to store commands, but how do we use this? Well lets add a few variables to shell.c: |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
command_table_t CommandTable[MAX_COMMANDS]; |
|||
command_table_t CommandTable[MAX_COMMANDS]; |
|||
</source> |
|||
This goes right above the function definitions. The first is a way to keep track of how many commands there are. The second is our command table. Ok, so now we have a "Command Table", but how to we access it? Well in order to add a command we need a function to do it. Add this below the other functions: |
This goes right above the function definitions. The first is a way to keep track of how many commands there are. The second is our command table. Ok, so now we have a "Command Table", but how to we access it? Well in order to add a command we need a function to do it. Add this below the other functions: |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
void add_new_command(char *name, char* description, void *function) |
|||
void add_new_command(char *name, char* description, void *function) |
|||
{ |
|||
if(NumberOfCommands + 1 < MAX_COMMANDS) |
|||
{ |
{ |
||
NumberOfCommands++; |
|||
{ |
|||
CommandTable[NumberOfCommands].name = name; |
|||
NumberOfCommands++; |
|||
CommandTable[NumberOfCommands].description = description; |
|||
CommandTable[NumberOfCommands].function = function; |
|||
} |
|||
CommandTable[NumberOfCommands].description = description; |
|||
return; |
|||
CommandTable[NumberOfCommands].function = function; |
|||
} |
|||
} |
|||
</source> |
|||
return; |
|||
} |
|||
Ok, now we are getting somewhere. We can add a command. But what about getting command line input? Thats up to our "shell()" function. But before we code that, lets add another variable: "char* input_string". Now for the shell function: |
Ok, now we are getting somewhere. We can add a command. But what about getting command line input? Thats up to our "shell()" function. But before we code that, lets add another variable: "char* input_string". Now for the shell function: |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
void shell() |
|||
void shell() |
|||
{ |
|||
{ |
|||
puts("\nMy_Prompt>"); |
|||
puts("\nMy_Prompt>"); |
|||
gets(input_string); |
|||
void (*command_run)(void); |
|||
void (*command_run)(void); |
|||
} |
|||
} |
|||
</source> |
|||
Ok, now we can get a string. But what about finding what command the user typed? Well we rely on old trusty "findCommand()" function for that one: |
Ok, now we can get a string. But what about finding what command the user typed? Well we rely on old trusty "findCommand()" function for that one: |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
int findCommand(char* command) |
|||
int findCommand(char* command) |
|||
{ |
|||
int i; |
|||
int ret; |
|||
for(i = 0; i < NumberOfCommands + 1; i++) |
|||
{ |
{ |
||
ret = strcmp(command, CommandTable[i].name); |
|||
int i; |
|||
int ret; |
|||
if(ret == 0) |
|||
return i; |
|||
else |
|||
return -1; |
|||
if(ret == 0) |
|||
{ |
|||
return i; |
|||
} |
|||
else |
|||
{ |
|||
return -1; |
|||
} |
|||
} |
|||
} |
} |
||
} |
|||
</source> |
|||
Now we need to add a little something right below "gets(input_string)", but above "void (*command_function)(void)": |
Now we need to add a little something right below "gets(input_string)", but above "void (*command_function)(void)": |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
int i = findCommand(input_string); |
|||
int i = findCommand(input_string); |
|||
if(i >= 0) |
|||
if(i >= 0) |
|||
{ |
|||
{ |
|||
command_function = CommandTable[i].function |
|||
command_function = CommandTable[i].function |
|||
command_function(); |
|||
command_function(); |
|||
} |
|||
} |
|||
else |
|||
else |
|||
{ |
|||
{ |
|||
return; |
|||
return; |
|||
} |
|||
return; |
|||
</source> |
|||
Now in our "init_shell()" function we need to add a few commands: |
Now in our "init_shell()" function we need to add a few commands: |
||
<source lang="c"> |
|||
/* shell.c */ |
|||
/* shell.c */ |
|||
add_new_command("help", "You code this one.", help_command); |
|||
add_new_command("help", "You code this one.", help_command); |
|||
add_new_command("", "", empty_command); |
|||
</source> |
|||
Now in our shell.h file: |
Now in our shell.h file: |
||
<source lang="c"> |
|||
extern void add_new_command(); |
|||
extern void add_new_command(); |
|||
extern void help_command(); |
|||
extern void empty_command(); |
|||
</source> |
|||
Now you need to code a void help_command function and a empty_command that manages null input, all it needs is a definition: |
Now you need to code a void help_command function and a empty_command that manages null input, all it needs is a definition: |
||
<source lang="c"> |
|||
void empty_command() |
|||
void empty_command() |
|||
{ |
|||
{ |
|||
} |
|||
} |
|||
</source> |
|||
An idea is to loop through all the command table and print the command name and description - for the help command. |
An idea is to loop through all the command table and print the command name and description - for the help command. |
Revision as of 10:12, 3 May 2015
Hello, this is a guide for writing a simple shell. Our shell with need a few things:
1. A working bootloader/GRUB 2. An IDT and IRQ handler 3. A GDT 4. A keyboard driver 5. A working text input/output system. 6. A set of string editing functions
First we need to make a file, shell.c, this file will contain all our functions and shell managers. The first function we need to write is our initialization function then our actual shell function.
/* shell.c */
void init_shell()
{
}
void shell()
{
}
Now you need to add "init_shell()" to your setup routine in your kernel.c file or whatever you named it, followed by a while loop running shell until the boolean "exit_status" is true.
Ok, now we need to write a few things. The first is command table, or a way to store our commands. I do this with a structure as follows:
/* shell.h */
#define MAX_COMMANDS 100
typedef struct
{
char *name;
char *description;
void *function;
} command_table_t;
Now we have a way to store commands, but how do we use this? Well lets add a few variables to shell.c:
/* shell.c */
command_table_t CommandTable[MAX_COMMANDS];
This goes right above the function definitions. The first is a way to keep track of how many commands there are. The second is our command table. Ok, so now we have a "Command Table", but how to we access it? Well in order to add a command we need a function to do it. Add this below the other functions:
/* shell.c */
void add_new_command(char *name, char* description, void *function)
{
if(NumberOfCommands + 1 < MAX_COMMANDS)
{
NumberOfCommands++;
CommandTable[NumberOfCommands].name = name;
CommandTable[NumberOfCommands].description = description;
CommandTable[NumberOfCommands].function = function;
}
return;
}
Ok, now we are getting somewhere. We can add a command. But what about getting command line input? Thats up to our "shell()" function. But before we code that, lets add another variable: "char* input_string". Now for the shell function:
/* shell.c */
void shell()
{
puts("\nMy_Prompt>");
gets(input_string);
void (*command_run)(void);
}
Ok, now we can get a string. But what about finding what command the user typed? Well we rely on old trusty "findCommand()" function for that one:
/* shell.c */
int findCommand(char* command)
{
int i;
int ret;
for(i = 0; i < NumberOfCommands + 1; i++)
{
ret = strcmp(command, CommandTable[i].name);
if(ret == 0)
return i;
else
return -1;
}
}
Now we need to add a little something right below "gets(input_string)", but above "void (*command_function)(void)":
/* shell.c */
int i = findCommand(input_string);
if(i >= 0)
{
command_function = CommandTable[i].function
command_function();
}
else
{
return;
}
return;
Now in our "init_shell()" function we need to add a few commands:
/* shell.c */
add_new_command("help", "You code this one.", help_command);
add_new_command("", "", empty_command);
Now in our shell.h file:
extern void add_new_command();
extern void help_command();
extern void empty_command();
Now you need to code a void help_command function and a empty_command that manages null input, all it needs is a definition:
void empty_command()
{
}
An idea is to loop through all the command table and print the command name and description - for the help command.
Whats left?
Add support for filesystem commands, a clear screen command, I don't know. But enjoy developing :)
- wxwsk8er