aboutsummaryrefslogtreecommitdiff
path: root/src/path.c
blob: 61c6cf7c86628775aed81fb04ceebebf57fb0f7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   path.c                                             :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: cacharle <marvin@42.fr>                    +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2020/02/27 15:51:01 by cacharle          #+#    #+#             */
/*   Updated: 2020/10/07 12:24:27 by cacharle         ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

/*
** \file   path.c
** \brief  Path search
*/

#include "minishell.h"

static int		st_path_check(char exec_path[PATH_MAX + 1], bool in_path)
{
	struct stat	statbuf;

	if (stat(exec_path, &statbuf) == -1)
		return (errorf_ret(127, "%s: %s\n", exec_path, strerror(errno)));
	if (S_ISDIR(statbuf.st_mode))
		return (errorf_ret(126, "%s: is a directory\n", exec_path));
	if (!in_path && !(statbuf.st_mode & 0444))
		return (errorf_ret(126, "%s: %s\n", exec_path, strerror(EACCES)));
	return (0);
}

static bool		st_dir_search(
	char *dirname, char *exec_name, char exec_path[PATH_MAX + 1])
{
	DIR				*dir;
	struct dirent	*entry;

	if ((dir = opendir(dirname)) == NULL)
		return (false);
	while ((entry = readdir(dir)) != NULL)
	{
		if (ft_strcmp(entry->d_name, exec_name) == 0)
		{
			ft_strcpy(exec_path, dirname);
			ft_strcat(exec_path, "/");
			ft_strcat(exec_path, exec_name);
			closedir(dir);
			return (true);
		}
	}
	closedir(dir);
	return (false);
}

int				path_search(
	t_env env, char *exec_name, char exec_path[PATH_MAX + 1], bool print)
{
	char	*current_dir;
	char	*collon;
	char	cwd[PATH_MAX + 1];

	if (ft_strchr(exec_name, '/') != NULL)
	{
		ft_strcpy(exec_path, exec_name);
		return (st_path_check(exec_path, false));
	}
	if ((current_dir = env_search(env, "PATH", NULL)) == NULL)
		return (st_dir_search(getcwd(cwd, PATH_MAX + 1), exec_name, exec_path));
	while ((collon = ft_strchr(current_dir, ':')) != NULL)
	{
		*collon = '\0';
		if (*current_dir == '\0')
			current_dir = getcwd(cwd, PATH_MAX + 1);
		if (st_dir_search(current_dir, exec_name, exec_path))
		{
			*collon = ':';
			return (st_path_check(exec_path, true));
		}
		*collon = ':';
		current_dir = collon + 1;
	}
	if (*current_dir == '\0')
		current_dir = getcwd(cwd, PATH_MAX + 1);
	if (st_dir_search(current_dir, exec_name, exec_path))
		return (st_path_check(exec_path, true));
	if (print)
		errorf("%s: command not found\n", exec_name);
	return (127);
}