Welcome to the Dark Side Mr Janiqua ;-).
Answering your questions one by one:
./configure
What people refer to as "commands" in Linux or UNIX is typically two kind of things:
- either a
shell
construct (a builtin
, a shell function
, an alias
),
etc.
- or an
executable
file
To provide you with some context here, what people refer to as shell
is typically a program, whose job is to accept some input, and then attempt to interpret that input, and act accordingly after that (execute it if it is an executable, etc).
When you enter some text into a shell, and then press enter, roughly the following happen:
- The shell tokenizes input, producing lexical tokens corresponding to the input provided. E.g consider that you type
gcc hello_world.c
into the shell. This will produce the following tokens gcc
and hello_world.c
- After tokenization, the shell will attempt to understand what the first token is (in our case
gcc
). It will first see if it is a shell construct
(a function, an alias, or a builtin) or if it is an absolute path
(the location relative to the root
directory) to an executable (something like /usr/bin/gcc
)
- If it is neither of the above, the shell will begin to lookup the directories listed in your
PATH
environment variable, to see if it can find a file with that same name.
- If it does find it, it usually get's executed[4] with the rest of the tokens passed to it as arguments. If it doesn't, it usually prints an error message like this[5]:
[23:25:59] nlightnfotis@mars : [~] $ lelos
bash: lelos: command not found...
Now, you, as a user, usually work in a specific directory tree in the file system, known as your user's home
folder, usually denoted as ~
. It's common that you, as a user, will actually write a program, or a shell script (a sequence of shell commands to be processed non-interactively).
Now, assuming you write a c program, and compile it to a hello
executable, you have two ways of executing it. The first one is moving or copying it to a directory that is in $PATH
(or adding the current folder to $PATH
, but for security reasons that's not a good idea) or executing it right from the folder you are. To do the latter, you use the dot slash
(./) to precede commands that you want the shell to execute, and lookup in the folder that you currently are in.
nano /something/something2
Is this something2 a file? It looks like a directory, I don't
understand how it can be edited? Same for ./configure. What does it
means?
In the UNIX world, the universal abstraction over everything is that of a file. What this means is that everything (or nearly everything for that matter), even if it is an image, a text file or even a device, is generally able to be read()
or write()
by any program that wishes to do so. As far as the operating system is concerned, it can be anything, but to the userspace application it will be presented as a sequence of bytes that is up to the application to choose how to present or manipulate.
A good first way to understand what something is, is by using the ls
command, using the -l
flag too. This will produce output that is similar to this:
[23:38:58] nlightnfotis@mars : [~] $ ls -l
-rw-r--r--. 1 nlightnfotis nlightnfotis 280906037 Jan 24 16:30 OpenSPARCT2.1.3.tar.bz2
drwxrwxr-x. 4 nlightnfotis nlightnfotis 4096 Jan 11 16:53 opt
Doing so will present you with several columns, with the first one corresponding to the permisions, the second one being the number of hardlinks, the third one being the file owner, the fourth being the file group, next one is the file size, followed by the modification time and last, but not least the filename.
To easily understand if something is a directory, you will notice the first letter in its permissions to be d
. That signals that object to be a directory.
If you still see a file, and are unsure about its nature, you can use a userspace utility called file
, that attempts to classify a file based on what is known as its magic number
, usually some bytes stored at or near the beginning. For instance running file
on that bzip2 file results in:
[23:45:54] nlightnfotis@mars : [~] $ file OpenSPARCT2.1.3.tar.bz2
OpenSPARCT2.1.3.tar.bz2: bzip2 compressed data, block size = 900k
For a text file, the output is similar to this:
[23:45:57] nlightnfotis@mars : [~] $ file report
report: ASCII text
Feel free to experiment with file
and different kind of files.
Now, to answer specifically to your
I don't understand how it can be edited?
question, the answer is very simple. As I mentioned earlier, everything is a sequence of bytes. You just change those bytes.
If it is a text file, you open it with a text editor, change a letter and then save. This corresponds to your text editor finding the offset in the file where that character is located, and change its bytes, to the bytes that represent the new character.
As far as binary (i.e not text) files are concerned, the answer is pretty simple:
Again you use some kind of software, either a piece of software that is designed specifically to handle that type of file, or you just use a hex editor (or just a plain text editor) to edit it. For instance, you can use vim
, a text editor, to edit a binary, such as python
like this: vim /usr/bin/python
. It will result in a screen like this:
The many weird characters in there, are just plain bytes that lack a representable character in ASCII. To enter hex view in vim, just type while inside it :%!xxd
. You will be presented with a screen like this:
Then proceed to edit the file, save (:wq
), and then exit hex view by typing :%!xxd -r
. Just be careful not to trash an important binary while experimenting, or do your experiments inside a virtual machine and you are all good.
Another useful tool you can use to view the bytes of any file is hexdump
. In fact, do try to create empty files or files with only a few characters, hexdump -C
them, and checkout the output and the ASCII table for a moment of enlightenment :)
If you want to see the (assembly) code that corresponds to those bytes (when we are talking about an executable), you can also use another tool, called objdump
to inspect them, likewise objdump -d /usr/bin/python
. In my screen it produces like this:
Hope all this was useful, and may the source be with you :)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Footnotes:
[4] The specific mechanisms behind that involve two UNIX system calls known as fork()
and exec()
. In code, the shell fork()
s itself to create a child process, which then proceeds to call exec()
with the first token as the first argument, to replace it's core image (the code) with the binary that it exec()
's to.
Working code for that is the following (dumped down a little bit to be as simple as possible):
pid = fork(); // pid is the process id returned by `fork()`
if(pid == 0) // in the child process, pid is zero
exec(argv[0], argv[1]); // if we are the child process, execute the argument that was given
[5] Okay, that whole shell explanation was a little bit simplistic, as there are more things that the shell does, like parsing for instance, because the command given to it might be more than just a simple executable with some arguments, and include redirections of output, pipes, etc that follow special courses of action, but still the overall description of what the shell does is pretty accurate. For a small and working shell, check out xv6's shell implementation