minishell/src/subst/wildcard_exp.c

164 lines
5.4 KiB
C
Raw Normal View History

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* wildcard_exp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
2025-03-08 17:32:47 +01:00
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
2025-03-06 17:37:08 +01:00
/* Created: 2025/02/23 15:02:59 by jguelen #+# #+# */
/* Updated: 2025/03/14 14:30:30 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
2025-03-06 12:45:05 +01:00
#include "ft_printf.h"
#include "subst.h"
#include "replace_substr.h"
2025-03-08 17:32:47 +01:00
/*
** TODO Pre-process file_pattern worddesc for a congruent marker string
*/
2025-03-06 17:37:08 +01:00
/******************************************************************************/
2025-03-08 17:32:47 +01:00
/* NOTE: The use of errno and the setting of it was OKed by Alexandru in this */
2025-03-06 17:37:08 +01:00
/* context. */
/******************************************************************************/
/*
2025-03-06 17:37:08 +01:00
** Returns a directory stream corresponding to the current directory.
**
*/
2025-03-06 17:37:08 +01:00
DIR *open_current_dir(void)
{
char *cur_dir_path;
size_t size;
DIR *dir;
size = PATH_SIZE_INIT;
cur_dir_path = malloc(size * sizeof(char));
if (!cur_dir_path)
return (NULL);
while (getcwd(cur_dir_path, size) == NULL)
{
if (errno != ERANGE)
return (NULL);
free(cur_dir_path);
size *= 2;
cur_dir_path = malloc(size * sizeof(char));
if (!cur_dir_path)
return (NULL);
}
errno = 0;
dir = opendir(cur_dir_path);
free(cur_dir_path);
return (dir);
}
/*
** TODO produce a clean marker string that denotes file_desc as issued from
** a pattern expansion or as quoted for possible spaces characters in the
** filename not to pose any possible issue.
2025-03-06 17:37:08 +01:00
*/
static t_wordlist *add_file_to_list(t_wordlist **list, char *filename)
{
t_worddesc *file_desc;
char *copy;
copy = ft_strdup(filename);
if (!copy)
return (wordlist_destroy(*list), NULL);
file_desc = worddesc_create(copy, '\0', NULL);
2025-03-06 17:37:08 +01:00
if (!file_desc)
{
wordlist_destroy(*list);
return (NULL);
}
*list = wordlist_push(*list, file_desc);
return (*list);
}
/*
2025-03-08 17:32:47 +01:00
** TODO Check if return value correct regarding the manual specifically the
2025-03-06 17:37:08 +01:00
** following:
** cf Bash scans each word for the character '*'.
**
** If one of these characters appears, and is not quoted, then the word is
** regarded as a PATTERN, and replaced with an alphabetically sorted list
** of filenames matching the pattern (see: Pattern Matching). If no matching
** filenames are found, the word is left unchanged.
2025-03-08 17:32:47 +01:00
** --> TODO this function should be provided with a properly pre-processed
** file_pattern where file_pattern->matcher denotes the quoted wildcards
** but the quotes themselves unquoted have been removed from word in a manner
** keeping the relationship between word and marker coherent.
2025-03-06 17:37:08 +01:00
*/
/*
** A function designed to present all possible * or ? filename expansions
** for the current directory. (? is not asked by the subject).
** Does not take into account any other wildcard and does only search the
** current working directory.
** @PARAM A C compliant character string representing a pattern for a filename.
2025-03-08 17:32:47 +01:00
** @RETURN Returns a wordlist for which each entry corresponds to a filename
** that matches pattern->word if any file matches in the current directory.
** Otherwise return file_pattern itself if nothing matches the perceived
** pattern. This list should be alphabetically sorted.
*/
static t_wordlist *expand_star_core(t_worddesc *file_pattern)
{
2025-03-06 17:37:08 +01:00
struct dirent *new;
DIR *current_dir;
t_wordlist *file_wordlist;
current_dir = open_current_dir();
if (current_dir == NULL)
return (NULL);
file_wordlist = NULL;
2025-03-08 17:32:47 +01:00
errno = 0;
2025-03-06 17:37:08 +01:00
new = readdir(current_dir);
while (new)
{
if (fits_pattern(new->d_name, file_pattern))
{
if (add_file_to_list(&file_wordlist, new->d_name) == NULL)
return (NULL);
}
errno = 0;
new = readdir(current_dir);
}
if (errno)
return (wordlist_destroy(file_wordlist), NULL);
if (!file_wordlist)
2025-03-08 17:32:47 +01:00
wordlist_push(file_wordlist, file_pattern);
return (wordlist_quicksort_full(file_wordlist));
}
/*
** TODO
** Pre-processes file_pattern to give it a proper marker chain and remove
** unquoted quotes from the pattern.
** Returns NULL in case of error.
** NOTE: This phase of pre-processing relies partly on processing done before
** it therefore checks more loosely (and quote removal still seems not to be
** done on string comming from a variable expansion) <-----TO RE-CHECK
*/
t_wordlist *expand_star(t_worddesc *file_pattern)
{
size_t i;
char *tmp;
i = 0;
while (file_pattern->word[i])
{
if (file_pattern->marker[i] != '\'' && file_pattern->marker[i] != '"'
&& file_pattern->marker[i] != '&' && file_pattern->marker[i] != '$'
&& (file_pattern->word[i] == '\'' || file_pattern->word[i] == '"'))
{
tmp = replace_in_str(file_pattern->word, i, i, NULL);
free(file_pattern->word);
file_pattern->word = tmp;
tmp = replace_in_str(file_pattern->marker, i, i, NULL);
free(file_pattern->marker);
file_pattern->marker = tmp;
2025-03-10 17:22:38 +01:00
continue ;
}
i++;
}
return (expand_star_core(file_pattern));
}