Commit graph

443 commits

Author SHA1 Message Date
Jérôme Guélen
32dd807c9d
(fix/enhancement): Added two tests for behaviour when not file corresponds 2025-04-28 11:50:36 +02:00
Jérôme Guélen
25ffc3fb6f
(fix): Proper behaviour for wildcards and proper test 2025-04-28 11:50:36 +02:00
Jérôme Guélen
e5952b3f43
Behaviour seems inconsistent 2025-04-28 11:50:32 +02:00
Jérôme Guélen
497f442d77
fix(expand-star): incomplete, committing to preserve 2025-04-28 11:48:13 +02:00
f0f19c3c0a fix(exec/and or): was exiting too soon 2025-04-25 18:03:12 +02:00
7a5e838fcf fix(debug): wrong indent for group_cmd 2025-04-25 17:53:40 +02:00
e1801652af fix(parsing/subshell): missing allocation for group cmd 2025-04-25 17:52:51 +02:00
9fcb34e1d5 feat(builtins/cd): on error, print path 2025-04-25 16:08:10 +02:00
29bbb5e572 fix(command_not_found): unset or empty PATH leads to No such file or directory error 2025-04-25 15:52:02 +02:00
c756d3783f tests(export): ensure export rejects invalid identifiers 2025-04-25 15:14:48 +02:00
c4be8693d1 tests(export): ensure export with extra = works 2025-04-25 15:10:05 +02:00
553783eb2d fix(tests): remove dependency on $HOME 2025-04-25 15:06:42 +02:00
f6ae16bbf8 tests(var_subst): ensure commands partially in variables work 2025-04-25 15:06:42 +02:00
a040ad5613 tests(export): ensure previous value of variable works correctly 2025-04-25 15:06:42 +02:00
Jérôme Guélen
29187f08da
tests(export/echo): ensure correct behaviour for single quotes in VAR 2025-04-25 15:01:54 +02:00
08baee41b6 tests(echo): ensure arguments in variables work 2025-04-25 14:40:09 +02:00
e5027323e1 fix(field_splitting): ensure no extraneous spaces appear
debug notes:
= 250  !! OK ===================================================================
export HOLA="bonjour "
echo $HOLA | cat -e
= out =
bonjour $

= err =
rc: 0

= refout =
bonjour$

++++++++++++++++++++++++++++++++++++++++++++++++++++
failed: quote removal before word splitting
++++++++++++++++++++++++++++++++++++++++++++++++++++
++++ test input:
export VAR="hello "
echo $VAR | cat -e
++++ Got output:
hello $
++++ But expected:
hello$

Problem is in post-processing:
parsed command
 ╰─ t_cmd
     ├─ t_cmd_type = FT_SIMPLE
     ├─ flags = 0
     ├─ line = 0
     ╰─ value
         ╰─ t_simple_cmd
             ├─ line = 0
             ├─ t_wordlist
             │   ├─ t_worddesc
             │   │   ├─ word   = [echo]
             │   │   ├─ marker = [    ]
             │   │   ├─ flags = 0
             │   │   ╰─ t_token_type = WORD_TOKEN
             │   ╰─ t_worddesc
             │       ├─ word   = [$VAR]
             │       ├─ marker = [    ]
             │       ├─ flags = 1
             │       ╰─ t_token_type = WORD_TOKEN
             ╰─ redirections = (empty redir list)
about to post-process
 ╰─ t_simple_cmd
     ├─ line = 0
     ├─ t_wordlist
     │   ├─ t_worddesc
     │   │   ├─ word   = [echo]
     │   │   ├─ marker = [    ]
     │   │   ├─ flags = 0
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ╰─ t_worddesc
     │       ├─ word   = [$VAR]
     │       ├─ marker = [    ]
     │       ├─ flags = 1
     │       ╰─ t_token_type = WORD_TOKEN
     ╰─ redirections = (empty redir list)
about to post-process
 ╰─ t_simple_cmd
     ├─ line = 0
     ├─ t_wordlist
     │   ├─ t_worddesc
     │   │   ├─ word   = [echo]
     │   │   ├─ marker = [    ]
     │   │   ├─ flags = 0
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ╰─ t_worddesc
     │       ├─ word   = [hello ]
     │       ├─ marker = [$$$$$$]
     │       ├─ flags = 1
     │       ╰─ t_token_type = WORD_TOKEN
     ╰─ redirections = (empty redir list)
about to post-process
 ╰─ t_simple_cmd
     ├─ line = 0
     ├─ t_wordlist
     │   ├─ t_worddesc
     │   │   ├─ word   = [echo]
     │   │   ├─ marker = [    ]
     │   │   ├─ flags = 0
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ├─ t_worddesc
     │   │   ├─ word   = [hello]
     │   │   ├─ marker = [$$$$$]
     │   │   ├─ flags = 1
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ╰─ t_worddesc <---- WHAT IS THIS DOING HERE???
     │       ├─ word   = []
     │       ├─ marker = []
     │       ├─ flags = 1
     │       ╰─ t_token_type = WORD_TOKEN
     ╰─ redirections = (empty redir list)
about to post-process
 ╰─ t_simple_cmd
     ├─ line = 0
     ├─ t_wordlist
     │   ├─ t_worddesc
     │   │   ├─ word   = [echo]
     │   │   ├─ marker = [    ]
     │   │   ├─ flags = 0
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ├─ t_worddesc
     │   │   ├─ word   = [hello]
     │   │   ├─ marker = [$$$$$]
     │   │   ├─ flags = 1
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ╰─ t_worddesc
     │       ├─ word   = []
     │       ├─ marker = []
     │       ├─ flags = 1
     │       ╰─ t_token_type = WORD_TOKEN
     ╰─ redirections = (empty redir list)
about to execute
 ╰─ t_simple_cmd
     ├─ line = 0
     ├─ t_wordlist
     │   ├─ t_worddesc
     │   │   ├─ word   = [echo]
     │   │   ├─ marker = [(null)]
     │   │   ├─ flags = 0
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ├─ t_worddesc
     │   │   ├─ word   = [hello]
     │   │   ├─ marker = [(null)]
     │   │   ├─ flags = 1
     │   │   ╰─ t_token_type = WORD_TOKEN
     │   ╰─ t_worddesc
     │       ├─ word   = []
     │       ├─ marker = [(null)]
     │       ├─ flags = 1
     │       ╰─ t_token_type = WORD_TOKEN
     ╰─ redirections = (empty redir list)

Problem seems to be in field splitting
2025-04-25 14:32:16 +02:00
588b016f69 tests(export): ensure variable substitution in variable names works 2025-04-25 13:41:43 +02:00
45869f1154 tests(export): ensure @ is accepted in variable values 2025-04-25 13:36:28 +02:00
297d68e73c tests(parsing): ensure unmatched ) are correctly reported 2025-04-25 13:33:09 +02:00
0c9dcd944e fix(parsing): report unclosed ( error 2025-04-25 13:19:44 +02:00
527a624765 fix(exec): return code 126 when command is found but permission denied 2025-04-25 12:40:34 +02:00
9d37d07589 fix(get_command_path): leak when path unset and calling file present in current dir
$ touch cat
$ unset PATH
$ cat
m==75845== Memcheck, a memory error detector
==75845== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==75845== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==75845== Command: ./minishell
==75845==
==75846== Memcheck, a memory error detector
==75846== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==75846== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==75846== Command: /nix/store/6wgd8c9vq93mqxzc7jhkl86mv6qbc360-coreutils-9.5/bin/touch cat
==75846==
==75846==
==75846== FILE DESCRIPTORS: 0 open (0 std) at exit.
==75846==
==75846== HEAP SUMMARY:
==75846==     in use at exit: 0 bytes in 0 blocks
==75846==   total heap usage: 46 allocs, 46 frees, 8,126 bytes allocated
==75846==
==75846== All heap blocks were freed -- no leaks are possible
==75846==
==75846== For lists of detected and suppressed errors, rerun with: -s
==75846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
minishell: cat: Permission denied
==75849==
==75849== FILE DESCRIPTORS: 3 open (3 std) at exit.
==75849==
==75849== HEAP SUMMARY:
==75849==     in use at exit: 4,181 bytes in 12 blocks
==75849==   total heap usage: 982 allocs, 970 frees, 122,299 bytes allocated
==75849==
==75849== 8 bytes in 1 blocks are definitely lost in loss record 1 of 9
==75849==    at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75849==    by 0x113C22: ft_calloc (ft_calloc.c:28)
==75849==    by 0x112399: get_paths_array (src/subst/simple_filename_exp.c:37)
==75849==    by 0x1121EE: filepath_from_env (src/subst/simple_filename_exp.c:144)
==75849==    by 0x1121C0: get_cmdpath (src/subst/simple_filename_exp.c:184)
==75849==    by 0x10CD97: exec_external_cmd (src/executing/simple_cmd/simple_cmd_execute.c:67)
==75849==    by 0x10CC58: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:94)
==75849==    by 0x10B12C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==75849==    by 0x10A4FD: execute_command (src/minishell.c:37)
==75849==    by 0x10A3B2: main (src/minishell.c:90)
==75849==
==75849== 24 bytes in 1 blocks are still reachable in loss record 6 of 9
==75849==    at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75849==    by 0x113C22: ft_calloc (ft_calloc.c:28)
==75849==    by 0x10D4A9: cmd_create (src/parser/cmd/cmd.c:20)
==75849==    by 0x10F6A1: simple_cmd_create (src/parser/simple_cmd/simple_cmd_parse.c:24)
==75849==    by 0x10F4E4: minishell_simple_cmd_parse (src/parser/simple_cmd/simple_cmd_parse.c:38)
==75849==    by 0x10E078: minishell_group_or_simple_parse (src/parser/group_cmd/group_cmd_parse.c:53)
==75849==    by 0x10E4AC: minishell_pipeline_parse (src/parser/pipeline/pipeline_parse.c:26)
==75849==    by 0x10D93C: minishell_cmds_parse (src/parser/cmd/cmds_parse.c:30)
==75849==    by 0x1139D5: minishell_parse (src/parser/cmd_parsing.c:67)
==75849==    by 0x10A38B: main (src/minishell.c:87)
==75849==
==75849== LEAK SUMMARY:
==75849==    definitely lost: 8 bytes in 1 blocks
==75849==    indirectly lost: 0 bytes in 0 blocks
==75849==      possibly lost: 0 bytes in 0 blocks
==75849==    still reachable: 24 bytes in 1 blocks
==75849==         suppressed: 4,149 bytes in 10 blocks
==75849==
==75849== For lists of detected and suppressed errors, rerun with: -s
==75849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
126
==75845==
==75845== FILE DESCRIPTORS: 3 open (3 std) at exit.
==75845==
==75845== HEAP SUMMARY:
==75845==     in use at exit: 4,201 bytes in 14 blocks
==75845==   total heap usage: 844 allocs, 830 frees, 72,248 bytes allocated
==75845==
==75845== 8 bytes in 1 blocks are definitely lost in loss record 1 of 8
==75845==    at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75845==    by 0x113C22: ft_calloc (ft_calloc.c:28)
==75845==    by 0x112399: get_paths_array (src/subst/simple_filename_exp.c:37)
==75845==    by 0x1121EE: filepath_from_env (src/subst/simple_filename_exp.c:144)
==75845==    by 0x1121C0: get_cmdpath (src/subst/simple_filename_exp.c:184)
==75845==    by 0x10CD97: exec_external_cmd (src/executing/simple_cmd/simple_cmd_execute.c:67)
==75845==    by 0x10CC58: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:94)
==75845==    by 0x10B12C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==75845==    by 0x10A4FD: execute_command (src/minishell.c:37)
==75845==    by 0x10A3B2: main (src/minishell.c:90)
==75845==
==75845== LEAK SUMMARY:
==75845==    definitely lost: 8 bytes in 1 blocks
==75845==    indirectly lost: 0 bytes in 0 blocks
==75845==      possibly lost: 0 bytes in 0 blocks
==75845==    still reachable: 0 bytes in 0 blocks
==75845==         suppressed: 4,193 bytes in 13 blocks
==75845==
==75845== For lists of detected and suppressed errors, rerun with: -s
==75845== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)inishell: cat: Permission denied
2025-04-24 18:03:25 +02:00
Jérôme Guélen
a86616f910
(enhancement) Printing an error on unclosed quote and corrected a typo. 2025-04-24 17:20:04 +02:00
Jérôme Guélen
3b5df9ec10
(fix) Dealing with signals correctly from the start 2025-04-24 14:28:07 +02:00
5fb054d403 fix(redirection): restore std fds on redirection error
debug notes:
$ cat << eof > /root/outfile
hello
eof
minishell: open: Permission denied
minishell: hello: command not found
==42382==
==42382== FILE DESCRIPTORS: 9 open (3 std) at exit.
==42382== Open file descriptor 8: /dev/pts/3
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9CC: handle_redirections (src/executing/simple_cmd/handle_redirections.c:65)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 7: /dev/pts/3
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9B9: handle_redirections (src/executing/simple_cmd/handle_redirections.c:64)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 6: /dev/pts/3
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9CC: handle_redirections (src/executing/simple_cmd/handle_redirections.c:65)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 5: /dev/pts/3
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9B9: handle_redirections (src/executing/simple_cmd/handle_redirections.c:64)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 4: /dev/pts/3
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9A6: handle_redirections (src/executing/simple_cmd/handle_redirections.c:63)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 3: /tmp/minishell_here_doc_78Ak8J9TeVu (deleted)
==42382==    at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382==    by 0x10C9A6: handle_redirections (src/executing/simple_cmd/handle_redirections.c:63)
==42382==    by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382==    by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382==    by 0x10A4DD: execute_command (src/minishell.c:37)
==42382==    by 0x10A3A2: main (src/minishell.c:89)
2025-04-24 13:47:54 +02:00
9db47dc96d feat(redirection): print path of redirection target on redirection error 2025-04-24 13:42:31 +02:00
b6e97ac2c7 fix(debug): redirectee prints both variants of an enum 2025-04-24 13:34:39 +02:00
3f08189aae fix(parsing/redirect): sometimes do not take a redirection into account
debug notes:

++++++++++++++++++++++++++++++++++++++++++++++++++++
failed: ambiguous redirect
++++++++++++++++++++++++++++++++++++++++++++++++++++
++++ test input:
export target="outfile1 outfile2"
echo hello > $target
echo $?
echo hi >> $target
echo $?
cat < $target
echo $?
ls
echo $?
++++ Got output:
hello
0
hi
0
echo $?
ls
echo $?
++++ But expected:
minishell: $target: ambiguous redirect
1
minishell: $target: ambiguous redirect
1
minishell: $target: ambiguous redirect
1
0

Reproduced this with rr record --cahos, see
/home/khais/.local/share/rr/minishell-48

$ export target="outfile1 outfile2"
$ echo hi > $target
hi

Break in simple_cmd_execute, second command has no redirections when it should
have some, presumably this comes from some uninitialized memory somewhere.
2025-04-24 13:26:40 +02:00
8d60113351 feat(postprocess/redir): remove quotes in redirection targets 2025-04-24 12:45:00 +02:00
ac198727e9 feat(postprocess): show error when post-processing failure occurs 2025-04-24 12:45:00 +02:00
2180909285 fix(expansion/wildcard): do not remove quotes twice on non-pattern strings
There is still an issue with removing too many quotes when expanding variables
(see #138). This will be tackled in a later PR.
2025-04-24 12:45:00 +02:00
aca85c3583 fix(expansion/redirection): prevent infinite loop of redir list pointing to itself
also add a hard limit of OVER 9000! iterations for the problematic loop
2025-04-24 12:45:00 +02:00
bf26afce2b fix(debug): correctly print here_doc_eof in redirect debug 2025-04-24 12:45:00 +02:00
38ffac7fc3 feat(redir): expand wildcards in targets and handle ambiguous redirects 2025-04-24 12:45:00 +02:00
920ad586e1 refactor(redirect): ambiguous redirect message to own file 2025-04-24 12:45:00 +02:00
2dd20b21bc feat(redir): fieldsplit redir target, and handle ambiguous redirects 2025-04-24 12:44:33 +02:00
5de82f2940 feat(debug): add function to easily treeprint a redirect 2025-04-21 11:00:14 +02:00
c00cc21ae4 feat(redirect): do variable expansion on redirect targets 2025-04-21 08:17:22 +02:00
2ae001e00b fix(exec/redirections): did not correctly restore fds when executing builtins
This caused redirections to keep stdout redirected to the outfile, which caused
problems with displaying the prmpt.

The shell hangs, but exits with C-d

Builtins affected:
echo hi > outfile
pwd > outfile
env > outfile
2025-04-18 14:14:43 +02:00
1499eaa985 test(builtin/export): ensure that variable substitution happens correctly 2025-04-18 10:37:49 +02:00
5fabec58d5 test(builtin/export): ensure that identifiers are correctly accepted or rejected 2025-04-18 10:30:21 +02:00
c5e15903e0 fix(builtin/export): show error on invalid identifiers such as % and $ 2025-04-18 10:17:21 +02:00
efaf4708f9 fix(builtin/export): empty arguments were not identified as invalid identifiers 2025-04-18 10:03:09 +02:00
6b2e15d301 test: migrate some tests from zms_testeur 2025-04-18 09:57:41 +02:00
d44691a5b0 fix(exec): running a command with an absolute path which does not exist now gives correct error
Before, it gave "Is a directory" error, but now it correctly gives "No such file
or directory".
2025-04-18 09:25:11 +02:00
655ff36351 fix(susbt/variable): empty variables on their own are removed 2025-04-18 09:22:18 +02:00
701174fc1b feat(debug): function to easily treeprint a worddesc 2025-04-18 09:20:49 +02:00
9271b7fa92 fix(parsing/pipeline): leak when optional pipeline returns NULL 2025-04-18 09:19:25 +02:00
6cc6e6cfb5 feat(debug): add function to easily treeprint a cmd 2025-04-17 12:28:57 +02:00