source: mainline/uspace/app/bdsh/README@ a56f4b2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a56f4b2 was 1b4b7b6, checked in by Tim Post <echo@…>, 17 years ago

Add a README to explain how things work

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