LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   writtign my own linux shell using BASH, guidelines? examples? thx (http://www.linuxquestions.org/questions/programming-9/writtign-my-own-linux-shell-using-bash-guidelines-examples-thx-637398/)

cocchiararo 04-23-2008 07:05 PM

writtign my own linux shell using BASH, guidelines? examples? thx
 
Hello, i've spent many days already searching and searching on the topic, and i couldnt find enough info to get me (and my team) started. We have (for our college) to write a shell that will be mounted (or whatever the correct translation for "montar" applies here) on bash (Debian etch). Its a basic shell (or so we have been told), but its something "extra", not explained on the clases or anything, so we are on our own here. (we only got a brieff explanation with examples on bash scripting, but google was more usefull on that matter than the class :P, but i wasnt able to find example shells or something that pointed us in the right direction, only a LOT of general info about shell scripting), but we know the basics of programing from other assingments/classes we had in the past.

What we must do:
-write a core for the shell, that will:
1) check if there are no modules loaded for the user that logs in
2) periodically check if the config files for the logged user has changed
3) some more stuff
4) always wait for input commands

* the modules are what will do stuff with the comands, there are some, the security one is for checking if the command entered is available to the user or not, for example

Now, the thing is, that we have not been able to find a simple (or complex, or whatever) shell, written in bash, to see how it works...

what we think for now, is that the main script will have a loop (while), and will keep waiting for commands to be entered... now.. how do we make it recieve the commands, and send em to the modules (if there is any) or to bash (if the command passed all the modules without errors, or if there are no modules loaded), or execute it by itself if it was a built in...


all this, while from time to time (set intervals), check for configuration changes :P

NOW, we still have many doubts about how to manage the commands entered... some options are:

read $variable, and work with the variable, but some commands (cd for example) seems not to work properly (we are still experimenting).

cat "something" (its not my idea and i didnt understand it well yet)

other ?

this is my first post in a programming forum, so i might not be doing it ok, so, my appologies, and any help will be appreciated.

jschiwal 04-23-2008 07:27 PM

I'm not sure if what you need to do is modify bash, such as loadable built-ins or if you are supposed to create your own shell.

For the former, read the "Learning the Bash Shell" book and/or "Bash Cookbook". Also
~/examples/loadables/* in any bash taqrball newer than 2.0. For the latter, maybe something like "Advanced Unix Programming" would be helpful.

But saying you want to write your own shell using bash doesn't make much sense. When the kernel loads in a program, it looks for the magic bytes to determine which shell should be used. If you use bash, then bash is the shell.

wrhansen 04-23-2008 07:38 PM

I had to write a shell in a class about a year ago. I wrote it in C though.
Our shell was a little different though, all it had to do was wait for the user to enter a command, and upon the user hitting "Enter" the shell would look at a file that contained a list of commands that the user was allowed to use, and if their command was in the list, the shell would fork a process and execute the command.

The very backbones of a shell is simple:

Code:

while( not some user inputted stop )
{
    Read User input
    If User input is a command
        Execute it
    Else
        Spit out an error
}

Edit-The above code is a really sloppy pseudo code.
Let me know if that helps, I can give some actual code samples( in C ) if you need. But I'll have to dig for them.


wrhansen

jschiwal 04-23-2008 07:58 PM

As this is a homework problem, we can't simply do the work for you. It is against the policy of this site. Also, you wouldn't learn what you need to. If you have something you are trying and need with some code you are writting, then we can help with that.

cocchiararo 04-23-2008 09:22 PM

i dont want to have my homework odne, thats why i explained very little about what i need to do :P

As i said, i must write a shell using bash scripts, the shell must loaded when a user who has it configured for himself, logs in.

But i dont want info on that, as i said, we know our way arround programming (more or less :P), but we have many doubts about "the beguining" (in this case, after the script is automatically loaded, inside the "while", we are unsure what method to use to "catch" the commands, and then send them to whatever applies.

we started with the most basic case, wich would be NO modules loaded, so the command gets sent to bash directly for procesing, and already run into trouble with some commands not working when we "stored" the command on a variable (using read).

as i said, it must be written using shell scripts, in bash.

any help thats admited by the site policy will be appreciated (an example, pointing in the right direction, some usefull/related section in guide, etc).

our first problem, as i said, is the method for taking the input and procesing it/deciding what to do with it.

pd: as for the pseudo code, its more or less similar to what we thought, we have the idea, but not the "knowledge/method" to code it :P (at least not the part we are having trouble with )

EDIT: if i undestood correctly, i cant get the beforementioned help, cause it is against the site policy ? if so, ill get what we have coded so far, post it here, and ask about what's not working, but not unltil tomorow or friday, we have a group meeting otmorow i think.

jschiwal 04-24-2008 02:55 AM

You have access in bash to argc & *argv[]. Also look at the "getopts" builtin as well as as the eval command.

cocchiararo 04-24-2008 07:18 AM

well, to hell with the weather, today i woke up to find the WORST fog in ages, imposible to leave home (college its like 70 km away).

our meeting is canceled, so i began the "experiments"

my partner wanted to use read to store the command in a variable, and then he was using it by doing the following:

echo $variable | bash

cd doesnt wokr with that (other commands do), but i dont know why he wants to do than instead of just:

$variable

here is a summary of the "homework":

The proyect is to develop a shell (from now on myshell) built only by shell scripting. Such script will be executed by (or over, dunno how to correctly translate) bash, wich is the default shell asociated to every user in linux.
Myshell primary caracteristics will be the posibility of adding/removing modules in a dinamic way, establish configurations for each user, and, by being "mounted over bash", use all the functionality that it offers. In this way, we can think of myshell as a wrapper of bash, to wich it adds functionalities.

maybe with that rough translation of the "introduction/summary"of the proyect, i make things clearer.

pd: ill look into what you mentioned, i havent heard of "getopts" before, not sure about eval, argc and *argv[] im familiar with in c, will look into it too, but if its similar to C in bash, i dont see how it can help with "our starting problems" :P

indienick 04-24-2008 08:13 AM

Essentially, I see cocchiararo's task as writing a Bash superset shell - on top of the very thing it's superseding (Bash).

Reading the project's summary, I would like to point out that a "wrapper" is something that extends functionality to another entity - GTK+ is in C, gnome-java is GTK+ for Java which is wrapped using the Java Native Interface.

The basic methodology here is:
  1. Write the basic shell routine, as wrhansen described.
  2. In each user's ~/.bashrc file, or in the system-wide /etc/profile, add a line to execute your shell every time a new shell is started.
  3. Make sure that when the user types "exit" to kill a shell session, it also kills the Bash session that is hosting your "myshell" session - this can be tricky.

cocchiararo 04-24-2008 09:46 AM

Quote:

Originally Posted by indienick (Post 3131415)
Essentially, I see cocchiararo's task as writing a Bash superset shell - on top of the very thing it's superseding (Bash).

Reading the project's summary, I would like to point out that a "wrapper" is something that extends functionality to another entity - GTK+ is in C, gnome-java is GTK+ for Java which is wrapped using the Java Native Interface.

The basic methodology here is:
  1. Write the basic shell routine, as wrhansen described.
  2. In each user's ~/.bashrc file, or in the system-wide /etc/profile, add a line to execute your shell every time a new shell is started.
  3. Make sure that when the user types "exit" to kill a shell session, it also kills the Bash session that is hosting your "myshell" session - this can be tricky.

most of the summary is translated by me, exept wrapper, that was in english, with its meaning translated to spanish between brackets.

i dint explain more, but configuring "myshell" to each user will be done with makefile, wich must have an option for install/configure/uninstall, and will be manually used by root/the administrator when they test our "myshell". (so we dont need to manually add anything, we must prepeare a makefile that does it)

for now we are trying to learn how to start writing our bash superset shell (thx naming our task XD), wich we are having trouble finding info/examples. (as i said, the basic idea is there, not how to correctly code it using a bash script :P )

the basic idea for the loop would be:

Code:

while( comand != exit)
{
    Read User input
    send it to loaded modules, one at a time
    if none returns an error msg
      execute it/send it to bash for execution (whichever aplies)
    Else
        Spit out an error
}

thats mostly pseudo code or worse :P
now, the thing is, if i write a script, lets say... like this (here there is no sending the comand to modules, its just executed, i thought that woul be an inteligent way to start :P):

Code:

#!/bin/bash
while [ COMANDO != exit ]
do
read COMANDO
$COMANDO
done

i get no promt between comands, nor can i "browse" to a previous command i may have used by pressing the up/down arrows.

ill KEEP investigating, but i already saw (forgot the past tense of read) many bash tutorials, and none informed me about how to start with this :P

indienick 04-24-2008 02:38 PM

I'm glad I could give your project a name! (jajajajaja) For getting some of that functionality, try searching for things like interpreting certain keystrokes within the shell; every keystroke sends a signal over its connector pins, it's just a matter of saying "when [this] keystroke is noticed, do [that]".

FYI: The past tense of "read" is, oddly enough, "read". It's just pronounced differently. In the present tense, it's pronounced as "reed", and in the past tense, "red".

ntubski 04-24-2008 06:11 PM

Quote:

i get no promt between comands, nor can i "browse" to a previous command i may have used by pressing the up/down arrows.
The read and history commands have some options that help with this:
Code:

$ help read
read: read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
    ... If the -p option is supplied, the string PROMPT is output without a trailing newline
    before attempting to read... If -e is supplied and
    the shell is interactive, readline is used to obtain the line...

$ help history
history: history [-c] [n] or history -awrn [filename] or history -ps arg [arg...]
    ...
    If the -s option is supplied, the non-option ARGs are appended to
    the history list as a single entry....

Quote:

i dont know why he wants to do than instead of just:

$variable
Try running echo foo | cat with this method and you'll see it doesn't give quite the same as the shell. This is where you should use eval:
Code:

$ help eval
eval: eval [arg ...]
    Read ARGs as input to the shell and execute the resulting command(s).


cocchiararo 04-24-2008 07:00 PM

Quote:

Originally Posted by ntubski (Post 3131974)
The read and history commands have some options that help with this:
Code:

$ help read
read: read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
    ... If the -p option is supplied, the string PROMPT is output without a trailing newline
    before attempting to read... If -e is supplied and
    the shell is interactive, readline is used to obtain the line...

$ help history
history: history [-c] [n] or history -awrn [filename] or history -ps arg [arg...]
    ...
    If the -s option is supplied, the non-option ARGs are appended to
    the history list as a single entry....



Try running echo foo | cat with this method and you'll see it doesn't give quite the same as the shell. This is where you should use eval:
Code:

$ help eval
eval: eval [arg ...]
    Read ARGs as input to the shell and execute the resulting command(s).


we had already found (well, not me, my parter thats has more experience :P ) about the -p for read (and he was really happy when i showed him this post about the -e part :P), but we are were unable for now to produce the decired prompt with it (an echo of $PS1 gives ${debian_chroot:+($debian_chroot)}\u@\h:\w\$, and an echo of that gives u@h:w$), but its the least of our problems for now).

about why he did echo "comand" | bash, after some testing i noticed that commands with pipes wouldnt work my way :(, but a cd command wont work his way either, so now we are looking into what you said.

thx for the help/info

EDIT: oh, just noticed you were telling me to use eval $comando, i kept reading and reading history and eval help until my teammate decided to try it instead :P

cocchiararo 04-30-2008 09:55 PM

Hello again !!

we've been doing a lot of work + reading

we are like 2/3 done i think, but we have a few things we are having trouble with.

for now ill bother you gentlemen with this:

one of the modules (the last one in fact, tho we skiped 2 to go to this one that seemed harder), needs to "establish a limitation on the ammount of outgoing IP packets (or paquets or packages, dunno how to translate :P)"

When the module detects (the module is run every X minutes,X is configurable, and only when run, it will do anything), that the amount of outgoing IP paquets (or the other options i mentioned earlier :P) is higher than the set number (we set this number), for each active process started in the current session that has 1 or more sockets with external conections, we must print on screen the sockets, and then kill the process.

I have no idea how to do this for now (im doing a different part), but my teammate spent the whole day researching, finally thought that he was going to get the desired info with "netstat --up -p", but when he runs that comand, besides some usefull info, he gets a msg saying:

(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)

and since he is using the command in a while loop, the message apears a few times.

he was really angry and went to bed :P any help/hint/push in the right direction will make him happier xD

chrism01 05-01-2008 12:25 AM

From the tcpdump man page
" When tcpdump finishes capturing packets, it will report counts of:

packets ``captured'' (this is the number of packets that tcpdump
has received and processed);

"

ntubski 05-01-2008 12:21 PM

Quote:

Originally Posted by cocchiararo (Post 3138350)
I have no idea how to do this for now (im doing a different part), but my teammate spent the whole day researching, finally thought that he was going to get the desired info with "netstat --up -p", but when he runs that comand, besides some usefull info, he gets a msg saying:

(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)

and since he is using the command in a while loop, the message apears a few times.

he was really angry and went to bed :P any help/hint/push in the right direction will make him happier xD

To hide the error message you could do "netstat --up -p 2>/dev/null", assuming the error message goes to standard error, and the useful info is on standard out. Otherwise you could do some filtering with grep/sed/awk/...


All times are GMT -5. The time now is 12:33 AM.