-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand_execution.c
More file actions
196 lines (180 loc) · 4.53 KB
/
command_execution.c
File metadata and controls
196 lines (180 loc) · 4.53 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include "shell.h"
/**
* execute_cd_command - executes the "cd" command to change directories.
* @args: array of command arguments.
* @env: array of character
* Description: This function handles the "cd" command, which is used to change
* directories. If no argument is provided, an error message is printed
* to standard error. If an argument is provided, the chdir function is called
* to change the current directory. If chdir fails, an error message is printed
* to standard error.
**/
void execute_cd_command(char *args[], char **env)
{
const char *error_msg;
if (args[1] == NULL)
{
error_msg = "cd: expected argument\n";
if (write(STDERR_FILENO, error_msg, _strlen(error_msg)) == -1)
{
perror("Write failed");
exit(EXIT_FAILURE);
}
}
else if (_strcmp(args[1], "-") == 0)
{
char *oldpwd = _getenv("OLDPWD", env);
if (oldpwd == NULL)
{
error_msg = "cd: OLDPWD not set\n";
if (write(STDERR_FILENO, error_msg, _strlen(error_msg)) == -1)
{
perror("Write failed");
exit(EXIT_FAILURE);
}
}
else
{
if (chdir(oldpwd) != 0)
perror("cd");
else
print_string(oldpwd);
}
}
else
{
if (chdir(args[1]) != 0)
perror("cd");
}
}
/**
* execute_command_in_path - Executes a command by
* searching in the system's PATH.
* @args: Array of command arguments.
* @error_message: Error message buffer.
* @length: Pointer to the length of the error message.
* @env: The environment variables array
* Description: This function searches for the command specified by
* the first argument in the args array within the directories listed in the
* system's PATH environment variable. If the command is found and
* is executable it is executed using the execve function.
* The error_message and length parameters are not used in this implementation.
**/
void execute_command_in_path(char *args[], char *error_message,
int *length, char **env)
{
char *path = _getenv("PATH", env);
char *dir = strtok(path, ":");
char exec_path[MAX_CMD_LEN];
(void)error_message;
(void)length;
while (dir != NULL)
{
_strcpy(exec_path, dir);
_strcat(exec_path, "/");
_strcat(exec_path, args[0]);
if (access(exec_path, X_OK) == 0)
{
execve(exec_path, args, env);
break;
}
dir = strtok(NULL, ":");
}
}
/**
* execute_other_command - Executes a command not handled by built-in commands.
* @args: Array of command arguments.
* @argv: Array of command-line arguments.
* @env: The environment variables array
* Description: This function forks a new process and attempts to execute the
* command specified by the first argument in the args array.
* If the execution fails, it tries to find the command in the system's PATH
* If the command is still not found, an error message is printed
* The parent process waits for the childm process
* to complete before continuing.
**/
void execute_other_command(char *args[], char *argv[], char **env)
{
int length = 0;
char error_message[1024];
pid_t pid;
if (!command_exists(args[0], env))
{
print_error_message(argv, args, error_message, length);
return;
}
pid = fork();
if (pid < 0)
{
handle_fork_error();
}
else if (pid == 0)
{
handle_child_process(args, argv, error_message, length, env);
}
else
{
handle_parent_process(pid);
}
}
/**
* execute_cmd - Executes a command
* @cmd: The command to be executed
* @argv: The arguments for the command
* @data: A pointer to the shell data
* @env: A pointer to the environment variables array
*/
void execute_cmd(char **cmd, char *argv[], shell_data *data, char **env)
{
char *args[MAX_CMD_LEN] = {NULL};
int i = 0;
(void)data;
while (cmd[i] != NULL)
{
args[i] = cmd[i];
i++;
}
args[i] = NULL;
if (args[0])
{
if (_strncmp(args[0], "cd", 2) == 0)
{
execute_cd(args, env);
}
else if (_strncmp(args[0], "env", 3) == 0)
{
execute_env(args, env);
}
else if (_strncmp(args[0], "setenv", 6) == 0)
{
execute_setenv(args, env);
}
else if (_strncmp(args[0], "unsetenv", 8) == 0)
{
execute_unsetenv(args, env);
}
else
{
execute_other_command(args, argv, env);
}
}
}
/**
* free_commands - Frees the memory occupied by the command history list.
* @data: Pointer to the shell_data struct.
* Description: This function traverses the command history list and frees
* the memory occupied by each node. After freeing the memory,
* the head of the history list is set to NULL.
**/
void free_commands(shell_data *data)
{
Node *current = data->head;
Node *next;
while (current != NULL)
{
next = current->next;
free(current);
current = next;
}
data->head = NULL;
}