The tokenization was built around the types not being allocated to lower
the number of failure points. This was achieved by creating a static
constant global array that holds all the possible values. The type
character pointer in every token then points to a value in this array.
This was exploited to make string comparison faster - instead of
comparing every character, only the address (the raw pointer) was
compared.
This was broken by moving the definition of the static global variable
into a header file. With that every file that includes it gets its own
version of the variable - its own memory - and te comparison fails.
The solution is the make an access function that holds the definition
of the static variable and all the other functions access the variable
through this function instead of directly. Now the variable is only ever
defined inside the function and address comparison works again.
Lukas Jiriste [Sat, 31 Aug 2024 09:06:49 +0000 (11:06 +0200)]
Improve Makefile
Make now tries to build Libft everytime but when libft.a stays the same
(no change made in Libft) the libft.a is considered not changed.
Before the libft.a was assumed to never be up to date (PHONY) hence the
minishell was always rebuilt.
Before that even the changes in Libft didn't trigger building of libft.a
when minishell make was run.
Lukas Jiriste [Sat, 31 Aug 2024 07:10:24 +0000 (09:10 +0200)]
Fix readline behaviour on SIGINT
Special signal handler is provided that uses readling functions.
I could not find info on whether the functions used in this handler are
reentrant but hopefully this will work.
Lukas Jiriste [Fri, 30 Aug 2024 15:36:49 +0000 (17:36 +0200)]
Make the forks close ALL fds except the needed ones
The recorsive (non-forking) ex_pipeline creates pipes that are inherited
by forked processes. These processes only need the latest opened pipe so
for the healt of other commands the other pipes should be closed.
Lukas Jiriste [Thu, 29 Aug 2024 14:19:07 +0000 (16:19 +0200)]
Add some signal handling for prompt
Signal handling for prompt is mostly done. Only generating a new prompt
when readline gets SIGINT and not erasing ^\ on ctrl-\ on NOLEAKS is
unresolved.
The expected behavior is to output a newline and a new prompt, readline
instead moves the cursor to the start of the current line while
preserving the prompt (so input rewrites the prompt).
Lilia-42 [Thu, 29 Aug 2024 09:22:25 +0000 (11:22 +0200)]
Fix piping of built-in functions
For piping/redirections of built-in functions the STD_FILENOs
are supposed to be dupped and saved. But the STDIN was dupped
3 times instead of each of STDIN, STDOUT, STDERR being dupped once.
Lukas Jiriste [Thu, 29 Aug 2024 08:06:53 +0000 (10:06 +0200)]
Change Makefile to permit usage of sigaction
The C99 standard does not include the sigaction function and structure
as they are (probably) GNU extensions. Using the GNU99 version instead
permits the extension usage.
Lukáš Jiřiště [Wed, 28 Aug 2024 08:34:29 +0000 (10:34 +0200)]
Make variable assignment possible in subshell
Because of ASSIGNMENT_WORD filtering, subshell needs a special rule (the
same as AND_IF, OR_IF) to permit variable assignment to be recognized
imediatelly after subshell starts.
Lukáš Jiřiště [Wed, 28 Aug 2024 07:59:34 +0000 (09:59 +0200)]
Make subshell execute in a new process
Because the OS keeps track of CWDs of its processes, subshell is made to
run in its own process not to change the CWD of main shell.
Also make exit the last executed command in a pipeline and in a program.
Lukáš Jiřiště [Tue, 27 Aug 2024 15:02:44 +0000 (17:02 +0200)]
Remove may_exit member of env
This was implemented to mimic the behaviour of piped exit.
But bash just runs piped commands in separate processes which leads to
piped builtins not having effect on the current session.
So I think it will be more pure without this check and if the bash
behaviour is needed, piping may be delegated to forked processes.
Lukáš Jiřiště [Tue, 27 Aug 2024 14:40:30 +0000 (16:40 +0200)]
Make env initialize properly
The last_was_builtin may be checked in ex_pipeline without
initialization because variable assignment does not run ex_fields
(which sets last_was_builtin).
Lukáš Jiřiště [Tue, 27 Aug 2024 09:37:57 +0000 (11:37 +0200)]
Fix pipeline behaviour
The return value is now set only after pipeline finishes (to the return
value of last command).
The shell also does not wait for each commmand in pipeline to end before
starting the following command (preventing getting stuck on full pipe).
Built-in functions still can get stuck when pipe gets full.
Lukáš Jiřiště [Tue, 27 Aug 2024 08:07:46 +0000 (10:07 +0200)]
Fix setting another value to exported variable
Instead of setting an exported variable to new value with the command of
the form <NAME>=<NEW_VALUE> a new non-exported variable was created and
used for variable expasion. The exported value was passed to child
processes.
This behaviour is fixed by this commit to the expected setting of
exported variable to the new value.
Lukáš Jiřiště [Mon, 26 Aug 2024 14:48:02 +0000 (16:48 +0200)]
Implement pipes and redirection for builtins
The feature is implemented except for error handling. Especially the
restoring of STD*_FILENO should be handled and exit the minishell hwne
they cannot be reopened.
Lukáš Jiřiště [Mon, 26 Aug 2024 14:16:51 +0000 (16:16 +0200)]
Fix tokenization double free
When an unclosed quotes are detected, tokenization fails. This causes
double free because the current_token is appended to tokens (because
current_token.size > 0) and is freed 4 lines below. The double free
happens when the tokens vector frees its memory.
In commit aac1d76 the tokenization was changed to set ASSIGNMENT_WORDs
to WORDs when the ASSIGNMENT_WORD is not in a proper place.
The filter however didn't check whether current token is ASSIGNMENT_WORD
hence other tokens could be changed to WORD also.
Lukas Jiriste [Fri, 23 Aug 2024 16:46:21 +0000 (18:46 +0200)]
Implement the export function, change tokenization
The tokenization had to be changed because "export te=te" was refused by
the parser. The "te=te" part was tokenized as ASSIGNMENT_WORD which can
only occur before command. So any ASSIGNMENT_WORD after command name is
now recognized as WORD.
Lukas Jiriste [Fri, 23 Aug 2024 14:19:22 +0000 (16:19 +0200)]
Fix showing single quotes upon expansion
In order for the wildcard expanded words not to be expanded again as
variables, single quotes were used for variable expansion. This however
caused single quotes to show when variable was expanded inside double
quotes.
The solution is to only quote the variables in wildcard expansion.
Lukas Jiriste [Thu, 22 Aug 2024 15:05:41 +0000 (17:05 +0200)]
Fix issues with patterns of form /*/
When introducing the handling of multiple slashed one after another
(eg. "///*") the handling of "/*/" patterns stopped working because the
asterisk could be assumed to be 0 symbols resulting in // which was
simplified to / effectively skipping a layer of dirs.
Lukas Jiriste [Thu, 22 Aug 2024 11:05:21 +0000 (13:05 +0200)]
Make wildcard expansion quoted
This is done for the expansion not to be expanded further for variable
names. This also prevents files with spae in their name to be split to
multiple tokens.
Lukas Jiriste [Fri, 2 Aug 2024 16:51:44 +0000 (18:51 +0200)]
Make the parsing table structure static
This makes it a little more memory and CPU friendly, because the table
doesn't need to be reallocated and parsed from the text form every
command. The downside itt needs to be cleared at the end of the program.
Lukas Jiriste [Fri, 2 Aug 2024 12:33:51 +0000 (14:33 +0200)]
Add parsing table and rules to the source code
This is done so that minishell does not have to load them from files
preventing minishell from not being able to find the files when being
moved around.
Lukas Jiriste [Thu, 1 Aug 2024 13:53:02 +0000 (15:53 +0200)]
Simplify t_redirection
Due to changes in f561c16753dcf7649b222c9b2e0fe6ca2445b6b9 it is
possible to get rid of created attribute of t_redirection.
It was included because of the same confusion as was talked in that
commit.
Lukas Jiriste [Thu, 1 Aug 2024 12:34:30 +0000 (14:34 +0200)]
Implement pipe duping
The order of closing the ends of pipes in ex_pipeline is done because
the reading end does not receive the eof unless the writting end is
closed. That means all file descriptors pointing to the writting end
have to be closed.
If the minishell itself only closes it after execution of the second
part of a pipe, it gets deadlocked, because minishell waits for the
process end to close the pipe and the process waits for the pipe to be
closed to exit.
Lukas Jiriste [Thu, 1 Aug 2024 07:30:06 +0000 (09:30 +0200)]
Make sure t_vecs are initialized before free
Short circuiting was meant to save the computation resources but causes
assignments not to be initialized when redirections encounter a problem.
This could be solved by initializing assignments outside of
save_assignments or by letting save_assignments initialize the
assignments even though it won't be used. I opted for the later.