Subversion Repositories HelenOS

Rev

Rev 3367 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3367 Rev 3414
1
BDSH - The Brain Dead Shell | Design Documentation
1
BDSH - The Brain Dead Shell | Design Documentation
2
--------------------------------------------------
2
--------------------------------------------------
3
 
3
 
4
Overview:
4
Overview:
5
=========
5
=========
6
 
6
 
7
BDSH was written as a drop in command line interface for HelenOS to permit
7
BDSH was written as a drop in command line interface for HelenOS to permit
8
interactive access to persistent file systems in development. BDSH was
8
interactive access to persistent file systems in development. BDSH was
9
written from scratch with a very limited userspace standard C library in
9
written from scratch with a very limited userspace standard C library in
10
mind. Much like the popular Busybox program, BDSH provides a very limited
10
mind. Much like the popular Busybox program, BDSH provides a very limited
11
shell with limited common UNIX creature comforts built in.
11
shell with limited common UNIX creature comforts built in.
12
 
12
 
13
Porting Busybox (and by extension ASH) would have taken much longer to
13
Porting Busybox (and by extension ASH) would have taken much longer to
14
complete, much less make stable due to stark differences between Linux and
14
complete, much less make stable due to stark differences between Linux and
15
Spartan with regards to IPC, term I/O and process creation. BDSH was written
15
Spartan with regards to IPC, term I/O and process creation. BDSH was written
16
and made stable within the space of less than 30 days.
16
and made stable within the space of less than 30 days.
17
 
17
 
18
BDSH will eventually evolve and be refined into the HelenOS equivalent
18
BDSH will eventually evolve and be refined into the HelenOS equivalent
19
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and
19
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and
20
use of strictly lower level functions makes it extremely easy to port.
20
use of strictly lower level functions makes it extremely easy to port.
21
 
21
 
22
Design:
22
Design:
23
=======
23
=======
24
 
24
 
25
BDSH is made up of three basic components:
25
BDSH is made up of three basic components:
26
 
26
 
27
 1. Main i/o, error handling and task management
27
 1. Main i/o, error handling and task management
28
 2. The builtin sub system
28
 2. The builtin sub system
29
 3. The module sub system
29
 3. The module sub system
30
 
30
 
31
The main part handles user input, reports errors, spawns external tasks and
31
The main part handles user input, reports errors, spawns external tasks and
32
provides a convenient entry point for built-in and modular commands. A simple
32
provides a convenient entry point for built-in and modular commands. A simple
33
structure, cliuser_t keeps track of the user's vitals, such as their current
33
structure, cliuser_t keeps track of the user's vitals, such as their current
34
working directory (and eventually uid, home directory, etc if they apply).
34
working directory (and eventually uid, home directory, etc if they apply).
35
 
35
 
36
This part defines and exposes all functions that are not intrinsic to a
36
This part defines and exposes all functions that are not intrinsic to a
37
certain built in or modular command. For instance: string handlers,
37
certain built in or modular command. For instance: string handlers,
38
module/builtin search and launch functions, error handlers and other things
38
module/builtin search and launch functions, error handlers and other things
39
can be found here.
39
can be found here.
40
 
40
 
41
Builtin commands are commands that must have access to cliuser_t, which is
41
Builtin commands are commands that must have access to cliuser_t, which is
42
not exposed to modular commands. For instance, the 'cd' command must update
42
not exposed to modular commands. For instance, the 'cd' command must update
43
the current working directory, which is stored in cliuser_t. As such, the
43
the current working directory, which is stored in cliuser_t. As such, the
44
entry types for builtin commands are slightly different.
44
entry types for builtin commands are slightly different.
45
 
45
 
46
Modular commands do not need anything more than the basic functions that are
46
Modular commands do not need anything more than the basic functions that are
47
exposed by default. They do not need to modify cliuser_t, they are just self
47
exposed by default. They do not need to modify cliuser_t, they are just self
48
contained. A modular command could very easily be made into a stand alone
48
contained. A modular command could very easily be made into a stand alone
49
program, likewise any stand alone program could easily become a modular
49
program, likewise any stand alone program could easily become a modular
50
command.
50
command.
51
 
51
 
52
Both modular and builtin commands share two things in common. Both must have
52
Both modular and builtin commands share two things in common. Both must have
53
two entry points, one to invoke the command and one to invoke a help display
53
two entry points, one to invoke the command and one to invoke a help display
54
for the command. Exec (main()) entry points are int * and are expected to
54
for the command. Exec (main()) entry points are int * and are expected to
55
return a value. Help entry points are void *, no return value is expected.
55
return a value. Help entry points are void *, no return value is expected.
56
 
56
 
57
They are typed as such (from cmds.h):
57
They are typed as such (from cmds.h):
58
 
58
 
59
/* Types for module command entry and help */
59
/* Types for module command entry and help */
60
typedef int * (* mod_entry_t)(char **);
60
typedef int (* mod_entry_t)(char **);
61
typedef void * (* mod_help_t)(unsigned int);
61
typedef void (* mod_help_t)(unsigned int);
62
 
62
 
63
/* Built-in commands need to be able to modify cliuser_t */
63
/* Built-in commands need to be able to modify cliuser_t */
64
typedef int * (* builtin_entry_t)(char **, cliuser_t *);
64
typedef int (* builtin_entry_t)(char **, cliuser_t *);
65
typedef void * (* builtin_help_t)(unsigned int);
65
typedef void (* builtin_help_t)(unsigned int);
66
 
66
 
67
As you can see, both modular and builtin commands expect an array of
67
As you can see, both modular and builtin commands expect an array of
68
arguments, however bulitins also expect to be pointed to cliuser_t.
68
arguments, however bulitins also expect to be pointed to cliuser_t.
69
 
69
 
70
Both are defined with the same simple structure:
70
Both are defined with the same simple structure:
71
 
71
 
72
/* Module structure */
72
/* Module structure */
73
typedef struct {
73
typedef struct {
74
	char *name;         /* Name of the command */
74
	char *name;         /* Name of the command */
75
	char *desc;         /* Description of the command */
75
	char *desc;         /* Description of the command */
76
	mod_entry_t entry;  /* Command (exec) entry function */
76
	mod_entry_t entry;  /* Command (exec) entry function */
77
	mod_help_t help;    /* Command (help) entry function */
77
	mod_help_t help;    /* Command (help) entry function */
78
	int restricted;     /* Restricts to interactive/non-interactive only */
78
	int restricted;     /* Restricts to interactive/non-interactive only */
79
} module_t;
79
} module_t;
80
 
80
 
81
NOTE: Builtin commands may grow in this respect, that is why they are
81
NOTE: Builtin commands may grow in this respect, that is why they are
82
defined separately.
82
defined separately.
83
 
83
 
84
Builtins, of course, would use the builtin_entry_t type. The name of the
84
Builtins, of course, would use the builtin_entry_t type. The name of the
85
command is used to associate user input to a possible entry point. The
85
command is used to associate user input to a possible entry point. The
86
description is a short (40 - 60 chars) summary of what the command does. Both
86
description is a short (40 - 60 chars) summary of what the command does. Both
87
entry points are then defined, and the restrict value is used to determine a
87
entry points are then defined, and the restrict value is used to determine a
88
commands availability.
88
commands availability.
89
 
89
 
90
Restriction levels are easy, a command is either available exclusively within
90
Restriction levels are easy, a command is either available exclusively within
91
interactive mode, exclusively within non-interactive mode or both. If you are
91
interactive mode, exclusively within non-interactive mode or both. If you are
92
looking at a prompt, you are in interactive mode. If you issue a command like
92
looking at a prompt, you are in interactive mode. If you issue a command like
93
this:
93
this:
94
 
94
 
95
/sbin/bdsh command [arg1] [arg2]
95
/sbin/bdsh command [arg1] [arg2]
96
 
96
 
97
... you are in non interactive mode. This is done when you need to force the
97
... you are in non interactive mode. This is done when you need to force the
98
parent shell to be the one who actually handles the command, or ensure that
98
parent shell to be the one who actually handles the command, or ensure that
99
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode.
99
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode.
100
 
100
 
101
The values are:
101
The values are:
102
  0 : Unrestricted
102
  0 : Unrestricted
103
 -1 : Interactive only
103
 -1 : Interactive only
104
  1 : Non-interactive only
104
  1 : Non-interactive only
105
 
105
 
106
A script to generate skeletal files for a new command is included, it can be
106
A script to generate skeletal files for a new command is included, it can be
107
found in cmds/mknewcmd. To generate a new modular command named 'foo', which
107
found in cmds/mknewcmd. To generate a new modular command named 'foo', which
108
should also be reachable by typing 'f00', you would issue this command:
108
should also be reachable by typing 'f00', you would issue this command:
109
 
109
 
110
./mknewcmd -n foo -a f00 -t module
110
./mknewcmd -n foo -a f00 -t module
111
 
111
 
112
This generates all needed files and instructs you on how to include your new
112
This generates all needed files and instructs you on how to include your new
113
command in the build and make it accessible. By default, the command will be
113
command in the build and make it accessible. By default, the command will be
114
unrestricted. Builtin commands can be created by changing 'module' to
114
unrestricted. Builtin commands can be created by changing 'module' to
115
'builtin'
115
'builtin'
116
 
116
 
117
There are more options to mknewcmd, which allow you to specify the
117
There are more options to mknewcmd, which allow you to specify the
118
description, entry point, help entry point, or restriction. By default, names
118
description, entry point, help entry point, or restriction. By default, names
119
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command',
119
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command',
120
etc. If you want to see the options and explanations in detail, use
120
etc. If you want to see the options and explanations in detail, use
121
./mknewcmd --help.
121
./mknewcmd --help.
122
 
122
 
123
When working with commands, keep in mind that only the main and help entry
123
When working with commands, keep in mind that only the main and help entry
124
points need to be exposed. If commands share the same functions, put them
124
points need to be exposed. If commands share the same functions, put them
125
where they are exposed to all commands, without the potential oops of those
125
where they are exposed to all commands, without the potential oops of those
126
functions going away if the command is eliminated in favor of a stand alone
126
functions going away if the command is eliminated in favor of a stand alone
127
external program.
127
external program.
128
 
128
 
129
The util.c file is a great place to put those types of functions.
129
The util.c file is a great place to put those types of functions.
130
 
130
 
131
Also, be careful with globals, option structures, etc. The compiler will
131
Also, be careful with globals, option structures, etc. The compiler will
132
generally tell you if you've made a mistake, however declaring:
132
generally tell you if you've made a mistake, however declaring:
133
 
133
 
134
volatile int foo
134
volatile int foo
135
 
135
 
136
... in a command will allow for anything else to pick it up. Sometimes
136
... in a command will allow for anything else to pick it up. Sometimes
137
this could be desirable .. other times not. When communicating between
137
this could be desirable .. other times not. When communicating between
138
builtins and the main system, try to use cliuser_t. The one exception
138
builtins and the main system, try to use cliuser_t. The one exception
139
for this is the cli_quit global, since everything may at some point
139
for this is the cli_quit global, since everything may at some point
140
need to check it. Modules should only communicate their return value.
140
need to check it. Modules should only communicate their return value.
141
 
141
 
142
Symbolic constants that everything needs should go in the config.h file,
142
Symbolic constants that everything needs should go in the config.h file,
143
however this is not the place to define shared macros.
143
however this is not the place to define shared macros.
144
 
144
 
145
Making a program into a module
145
Making a program into a module
146
==============================
146
==============================
147
 
147
 
148
If you have some neat program that would be useful as a modular command,
148
If you have some neat program that would be useful as a modular command,
149
converting it is not very hard. The following steps should get you through
149
converting it is not very hard. The following steps should get you through
150
the process easily (assuming your program is named 'foo'):
150
the process easily (assuming your program is named 'foo'):
151
 
151
 
152
1: Use mknewcmd to generate the skeletal files.
152
1: Use mknewcmd to generate the skeletal files.
153
 
153
 
154
2: Change your "usage()" command as shown:
154
2: Change your "usage()" command as shown:
155
     -- void usage(...)
155
     -- void usage(...)
156
     ++ void * help_cmd_foo(unsigned int level)
156
     ++ void help_cmd_foo(unsigned int level)
157
     -- return;
-
 
158
     ++ retrn CMD_VOID;
-
 
159
 
157
 
160
     'level' is either 0 or 1, indicating the level of help requested.
158
     'level' is either 0 or 1, indicating the level of help requested.
161
     If the help / usage function currently exits based on how it is
159
     If the help / usage function currently exits based on how it is
162
     called, you'll need to change it.
160
     called, you'll need to change it.
163
 
161
 
164
3: Change the programs "main()" as shown:
162
3: Change the programs "main()" as shown:
165
     -- int main(int argc, char **argv)
163
     -- int main(int argc, char **argv)
166
     ++ int * cmd_foo(char **argv)
164
     ++ int cmd_foo(char **argv)
167
     -- return 1;
165
     -- return 1;
168
     ++ return CMD_FAILURE;
166
     ++ return CMD_FAILURE;
169
     -- return 0;
167
     -- return 0;
170
     ++ return CMD_SUCCESS;
168
     ++ return CMD_SUCCESS;
171
 
169
 
172
     If main() returns an int that is not 1 or 0 (e.g. 127), cast it as
-
 
173
     such:
-
 
174
 
-
 
175
     -- return 127;
-
 
176
     ++ return (int *) 127;
-
 
177
 
-
 
178
     NOTE: _ONLY_ the main and help entry points need to return int * or
-
 
179
     void *, respectively. Also take note that argc has changed. The type
-
 
180
     for entry points may soon change.
-
 
181
 
-
 
182
     NOTE: If main is void, you'll need to change it and ensure that its
170
     NOTE: If main is void, you'll need to change it and ensure that its
183
     expecting an array of arguments, even if they'll never be read or
171
     expecting an array of arguments, even if they'll never be read or
184
     used. I.e.:
172
     used. I.e.:
185
 
173
 
186
     -- void main(void)
174
     -- void main(void)
187
     ++ int * cmd_foo(char **argv)
175
     ++ int cmd_foo(char **argv)
188
 
-
 
189
     Similararly, do not try to return CMD_VOID within the modules main
-
 
190
     entry point. If somehow you escape the compiler yelling at you, you
-
 
191
     will surely see pretty blue and yellow fireworks once its reached.
-
 
192
 
176
 
193
4: Don't expose more than the entry and help points:
177
4: Don't expose more than the entry and help points:
194
     -- void my_function(int n)
178
     -- void my_function(int n)
195
     ++ static void my_function(int n)
179
     ++ static void my_function(int n)
196
 
180
 
197
5: Copy/paste to the stub generated by mknewcmd then add your files to the
181
5: Copy/paste to the stub generated by mknewcmd then add your files to the
198
   Makefile. Be sure to add any directories that you made to the SUBDIRS so
182
   Makefile. Be sure to add any directories that you made to the SUBDIRS so
199
   that a 'make clean' will clean them.
183
   that a 'make clean' will clean them.
200
 
184
 
201
Provided that all functions that your calling are available in the
185
Provided that all functions that your calling are available in the
202
userspace C library, your program should compile just fine and appear
186
userspace C library, your program should compile just fine and appear
203
as a modular command.
187
as a modular command.
204
 
188
 
205
Overcoming userspace libc obstacles
189
Overcoming userspace libc obstacles
206
===================================
190
===================================
207
 
191
 
208
A quick glance through the util.c file will reveal functions like
192
A quick glance through the util.c file will reveal functions like
209
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions
193
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions
210
that were missing from userspace libc when BDSH was born. Later, after
194
that were missing from userspace libc when BDSH was born. Later, after
211
porting what was needed from FBSD/NBSD, the real functions appeared in
195
porting what was needed from FBSD/NBSD, the real functions appeared in
212
the userspace libc after being tested in their cli_* implementations.
196
the userspace libc after being tested in their cli_* implementations.
213
 
197
 
214
Those functions remain because they guarantee that bdsh will work even
198
Those functions remain because they guarantee that bdsh will work even
215
on systems that lack them. Additionally, more BDSH specific stuff can
199
on systems that lack them. Additionally, more BDSH specific stuff can
216
go into them, such as error handling and reporting when malloc() fails.
200
go into them, such as error handling and reporting when malloc() fails.
217
 
201
 
218
You will also notice that FILE, fopen() (and all friends), ato*() and
202
You will also notice that FILE, fopen() (and all friends), ato*() and
219
other common things might be missing. The HelenOS userspace C library is
203
other common things might be missing. The HelenOS userspace C library is
220
still very young, you are sure to run into something that you want/need
204
still very young, you are sure to run into something that you want/need
221
which is missing.
205
which is missing.
222
 
206
 
223
When that happens, you have three options:
207
When that happens, you have three options:
224
 
208
 
225
1 - Implement it internally in util.c , when its tested and stable send a
209
1 - Implement it internally in util.c , when its tested and stable send a
226
patch to HelenOS asking for your function to be included in libc. This is
210
patch to HelenOS asking for your function to be included in libc. This is
227
the best option, as you not only improve BDSH .. but HelenOS as a whole.
211
the best option, as you not only improve BDSH .. but HelenOS as a whole.
228
 
212
 
229
2 - Work around it. Not everyone can implement / port fopen() and all of
213
2 - Work around it. Not everyone can implement / port fopen() and all of
230
its friends. Make open(), read(), write() (etc) work if at all possible.
214
its friends. Make open(), read(), write() (etc) work if at all possible.
231
 
215
 
232
3 - Send an e-mail to the HelenOS development mailing list. Explain why you
216
3 - Send an e-mail to the HelenOS development mailing list. Explain why you
233
need the function and what its absence is holding up.
217
need the function and what its absence is holding up.
234
 
218
 
235
If what you need is part of a library that is typically a shared object, try
219
If what you need is part of a library that is typically a shared object, try
236
to implement a 'mini' version of it. Currently, all userspace applications
220
to implement a 'mini' version of it. Currently, all userspace applications
237
are statically linked. Giving up creature comforts for size while avoiding
221
are statically linked. Giving up creature comforts for size while avoiding
238
temporary 'band aids' is never frowned upon.
222
temporary 'band aids' is never frowned upon.
239
 
223
 
240
Most of all, don't get discouraged .. ask for some help prior to giving up
224
Most of all, don't get discouraged .. ask for some help prior to giving up
241
if you just can't accomplish something with the limited means provided.
225
if you just can't accomplish something with the limited means provided.
242
 
226
 
243
Contributing
227
Contributing
244
============
228
============
245
 
229
 
246
I will take any well written patch that sanely improves or expands BDSH. Send
230
I will take any well written patch that sanely improves or expands BDSH. Send
247
me a patch against the trunk revision, or, if you like a Mercurial repository
231
me a patch against the trunk revision, or, if you like a Mercurial repository
248
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with
232
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with
249
the trunk.
233
the trunk.
250
 
234
 
251
Please be sure to follow the simple coding standards outlined at
235
Please be sure to follow the simple coding standards outlined at
252
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your
236
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your
253
changes and make sure your patch applies cleanly against the latest revision.
237
changes and make sure your patch applies cleanly against the latest revision.
254
 
238
 
255
All patches submitted must be your original code, or a derivative work of
239
All patches submitted must be your original code, or a derivative work of
256
something licensed under the same 3 clause BSD license as BDSH. See LICENSE
240
something licensed under the same 3 clause BSD license as BDSH. See LICENSE
257
for more information.
241
for more information.
258
 
242
 
259
When sending patches, you agree that your work will be published under the
243
When sending patches, you agree that your work will be published under the
260
same 3 clause BSD license as BDSH itself. Failure to ensure that anything
244
same 3 clause BSD license as BDSH itself. Failure to ensure that anything
261
you used is not under the same or less restrictive license could cause major
245
you used is not under the same or less restrictive license could cause major
262
issues for BDSH in the future .. please be sure. Also, please don't forget
246
issues for BDSH in the future .. please be sure. Also, please don't forget
263
to add yourself in the AUTHORS file, as I am horrible about keeping such
247
to add yourself in the AUTHORS file, as I am horrible about keeping such
264
things up to date.
248
things up to date.
265
 
249
 
266
 
250
 
267
 
251
 
268
 
252
 
269
 
253