-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from nanafox/updates/aliases
Improved aliases
- Loading branch information
Showing
6 changed files
with
234 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,151 @@ | ||
#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) | ||
int handle_alias(alias_t **head, char *command) | ||
{ | ||
char *value, *loc, *name, *tmp; | ||
ssize_t i, offset, exit_code = 0; | ||
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); | ||
} | ||
|
||
if (!_strcmp("unalias", command[0])) | ||
else if (!_strncmp(command, "unalias", 7)) | ||
return (unalias(head, command)); | ||
if ((!_strcmp(command[0], "alias") && command[1] == NULL)) | ||
print_aliases(*head); | ||
for (i = 1; command[i] != NULL; i++) | ||
|
||
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) | ||
{ | ||
tmp = _strdup(command[i]); | ||
loc = _strchr(tmp, '='); | ||
if (loc != NULL) | ||
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 */ | ||
{ | ||
offset = (&loc[0]) - (&tmp[0]); | ||
tmp[offset] = '\0'; | ||
name = _strdup(tmp); | ||
if (name == NULL) | ||
{ | ||
safe_free(tmp); | ||
return (-1); | ||
} | ||
value = (tmp[offset + 1] == '"' || tmp[offset + 1] == '\'') | ||
? extract_value(&tmp[offset + 1]) : _strdup(&tmp[offset + 1]); | ||
if (value == NULL) | ||
{ | ||
multi_free("ss", value, name); | ||
return (-1); | ||
} | ||
if (add_alias(head, name, value) == NULL) | ||
_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) | ||
{ | ||
multi_free("ss", value, name); | ||
return (-1); | ||
exit_code = print_alias(aliases, token); | ||
token = strtok(NULL, " "); | ||
} | ||
multi_free("ss", value, name); | ||
} | ||
else | ||
exit_code = print_alias(*head, command[i]); | ||
safe_free(tmp); | ||
exit_code = print_alias(aliases, token); | ||
} | ||
return (exit_code); | ||
free(dup); | ||
} | ||
|
||
/** | ||
* extract_value - returns the string value enclosed in quotes | ||
* @value: the string containing value | ||
* | ||
* Return: the string data without the quotes | ||
* 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 | ||
*/ | ||
char *extract_value(const char *value) | ||
void build_alias_cmd(char ***sub_command, char *alias_value) | ||
{ | ||
int i, j; | ||
char quote = value[0]; | ||
int length = strlen(value); | ||
char *content = malloc(length); | ||
char **dup_array = NULL; | ||
|
||
if (content == NULL) | ||
if ((*sub_command)[1] != NULL) | ||
{ | ||
return (NULL); | ||
} | ||
/* save a copy of the the commands array, excluding the alias */ | ||
dup_array = duplicate_str_array((*sub_command) + 1); | ||
|
||
/* 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); | ||
|
||
for (i = 1, j = 0; i < length && value[i] != quote; ++i, ++j) | ||
/* clean up and return */ | ||
free_str(dup_array); | ||
} | ||
else | ||
{ | ||
content[j] = value[i]; | ||
/* there was alias alright but no other arguments */ | ||
free_str(*sub_command); | ||
*sub_command = _strtok(alias_value, NULL); | ||
} | ||
content[j] = '\0'; | ||
|
||
return (content); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.