-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathexec.c
129 lines (121 loc) · 3.15 KB
/
exec.c
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "env.h"
#include "path.h"
#include "execution.h"
#include "minishell.h"
/*
* find executable file in dirpath.
*
* filename: filename
* dirpath: the directory to search
*
* return: fullpath of found executable file,
* otherwise return NULL.
*/
char *find_executable_file_in_dir(char *filename, char *dirpath)
{
DIR *dir;
struct dirent *dirp;
struct stat buf;
char *fullpath;
dir = opendir(dirpath);
if (!dir)
return (NULL);
dirp = readdir(dir);
while (dirp)
{
if (ft_strcmp(dirp->d_name, filename) == 0)
{
fullpath = path_join(dirpath, dirp->d_name);
if (!fullpath)
return (free_and_rtn_ptr(dir, NULL));
if (stat(fullpath, &buf) == 0 && S_ISREG(buf.st_mode))
return (free_and_rtn_ptr(dir, fullpath));
free(fullpath);
}
dirp = readdir(dir);
}
return (free_and_rtn_ptr(dir, NULL));
}
/*
* This function search file in directories in dirs and try to execute.
*/
static char *search_and_exec_file_from_dirs(char *filename,
char **argv, char **dirs)
{
char **envs;
int i;
char *executable_path;
char *last_executable_path;
i = 0;
last_executable_path = NULL;
envs = vars2environ(g_shell.vars);
while (dirs[i])
{
if (dirs[i])
executable_path = find_executable_file_in_dir(filename, dirs[i]);
if (executable_path)
{
free(last_executable_path);
last_executable_path = ft_strdup(executable_path);
execve(executable_path, argv, envs);
}
free(executable_path);
i++;
}
free_ptrarr((void **)envs);
return (last_executable_path);
}
/*
* This function search file in directories in $PATH and try to execute.
*/
char *search_and_exec_file_from_path_env(char *filename, char **argv)
{
t_var *path_env_var;
char **dirs;
char *last_executable_path;
path_env_var = get_env("PATH");
if (!path_env_var || !path_env_var->value)
return (NULL);
dirs = get_colon_units(path_env_var->value, "./");
last_executable_path = search_and_exec_file_from_dirs(filename, argv, dirs);
free_ptrarr((void **)dirs);
return (last_executable_path);
}
/*
* This function works just like execvp.
*
* filename: filename or filepath.
* argv: arguments that is passed to execution program
*
* return: If exec command successful, no value will be returned.
* This function returning value means exec or other function is failed.
*/
int cmd_execvp(char *filename, char **argv)
{
char *executable_path;
errno = 0;
executable_path = filename;
if (ft_strchr(filename, '/'))
execve(filename, argv, vars2environ(g_shell.vars));
else
executable_path = search_and_exec_file_from_path_env(filename, argv);
if (executable_path && is_directory(executable_path))
put_minish_err_msg_and_exit(126, executable_path, "Is a directory");
if (errno == ENOEXEC && is_executable(executable_path))
exit(0);
else if (errno == ENOEXEC && !is_executable(executable_path))
errno = EACCES;
if (errno && executable_path)
put_minish_err_msg(executable_path, strerror(errno));
else
put_minish_err_msg(filename, "command not found");
if (errno && errno != ENOENT)
exit(126);
exit(127);
}