-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathalias_handler.c
159 lines (140 loc) · 4.43 KB
/
alias_handler.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
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
#include "shell.h"
static int exit_code;
/**
* handle_alias - handles the processing of alias
* @head: a pointer to the list containing all aliases
* @command: the list of commands containing alias-specific lines
*
* Return: 0 on success, -1 on error
*/
int handle_alias(alias_t **head, char *command)
{
while (*command == ' ')
command++; /* remove all the leading spaces */
if (_strlen(command) == 5)
print_aliases(*head);
else if (!_strncmp(command, "alias", 5))
{
if (!_strchr(command, '='))
process_non_matching(*head, command + 5, 1);
else
parse_aliases(command, head);
}
else if (!_strncmp(command, "unalias", 7))
return (unalias(head, command));
return (exit_code);
}
/**
* parse_aliases - extract aliases from the input string using regular
* expressions.
* @input: the input string containing aliases
* @aliases: a pointer to a list of aliases
*
* Description: This function uses regular expressions to extract aliases from
* the input string. It populates the provided array of Alias structures with
* the parsed aliases and updates the aliasCount accordingly.
*/
void parse_aliases(const char *input, alias_t **aliases)
{
char *input_ptr = NULL;
size_t valueLength, alias_count = 0;
regmatch_t matches[3];
regex_t regex;
const char *pattern =
"([^\"]\\S*|\"[^\"]*\"|'[^\']*')=([^\"]\\S*|\"[^\"]*\"|'[^\']*')";
if (regcomp(®ex, pattern, REG_EXTENDED) != 0)
return; /* regular expression compilation failed */
input_ptr = (char *)input;
while (regexec(®ex, input_ptr, 3, matches, 0) == 0)
{
char name[MAX_ALIAS_LENGTH] = {0};
char value[MAX_VALUE_LENGTH] = {0};
/* extract the alias name, accounts for the leading spaces */
_strncpy(name, (input_ptr + 1) + matches[1].rm_so,
(matches[1].rm_eo - 1) - matches[1].rm_so);
_strncpy(value, input_ptr + matches[2].rm_so,
matches[2].rm_eo - matches[2].rm_so); /* extract the alias value */
name[matches[1].rm_eo - matches[1].rm_so] = '\0';
valueLength = matches[2].rm_eo - matches[2].rm_so;
if (isquote(value[0])) /* remove quotes */
{
_strncpy(value, input_ptr + matches[2].rm_so + 1, valueLength - 2);
value[valueLength - 2] = '\0';
}
else /* not enclosed in quotes, copy as is */
value[valueLength] = '\0';
if (add_alias(aliases, name, value) == NULL)
return;
if (alias_count)
process_non_matching(*aliases, input_ptr, 0);
alias_count++; /* increment alias count */
input_ptr += matches[0].rm_eo; /* keep searching */
}
if (alias_count)
process_non_matching(*aliases, input_ptr, 1);
regfree(®ex);
}
/**
* process_non_matching - processes strings that do not have the `name=value`
* format while parsing aliases
* @aliases: a list containing aliases
* @non_matching: the string to check for non-matching patterns
* @end: used to signal the end. 1 means it can process the whole string at
* once. 0 means it can do only word token at a time
*/
void process_non_matching(alias_t *aliases, const char *non_matching, int end)
{
char *token, *dup;
if (non_matching == NULL || *non_matching == '\0')
return; /* there's nothing to work on, everything matched */
dup = _strdup(non_matching);
token = strtok(dup, " ");
/* it is non-matching if it doesn't contain an equal sign */
if (!_strchr(token, '='))
{
if (end)
{
while (token != NULL)
{
exit_code = print_alias(aliases, token);
token = strtok(NULL, " ");
}
}
else
exit_code = print_alias(aliases, token);
}
free(dup);
}
/**
* build_alias_cmd - builds the correct command line when the received input is
* a valid alias command
* @sub_command: a pointer to the array containing the commands
* @alias_value: the value of the alias command
*/
void build_alias_cmd(char ***sub_command, char *alias_value)
{
char **dup_array = NULL;
if ((*sub_command)[1] != NULL)
{
/* save a copy of the the commands array, excluding the alias */
dup_array = duplicate_str_array((*sub_command) + 1);
if (dup_array == NULL)
{
fprintf(stderr, "alias: Memory allocation failed\n");
return;
}
/* memory and build the command line string based on the alias value */
free_str(sub_command);
*sub_command = _strtok(alias_value, NULL);
/* concatenate both arrays to form a complete command string */
concatenate_arrays(sub_command, dup_array);
/* clean up and return */
free_str(&dup_array);
}
else
{
/* there was alias alright but no other arguments */
free_str(sub_command);
*sub_command = _strtok(alias_value, NULL);
}
}