feat(userspace/coreutils): add alias command

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-16 00:54:59 +00:00
parent babf792c30
commit 49ee634822
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A

View File

@ -0,0 +1,225 @@
/*
This file is part of Fennix Core Utilities.
Fennix Core Utilities is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Core Utilities is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Core Utilities. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
typedef struct alias_t
{
char *name;
char *value;
struct alias_t *next;
} alias_t;
alias_t *aliases = NULL;
void FreeAliases()
{
alias_t *current = aliases;
while (current != NULL)
{
alias_t *next = current->next;
free(current->name);
free(current->value);
free(current);
current = next;
}
aliases = NULL;
}
alias_t *FindAlias(const char *name)
{
alias_t *current = aliases;
while (current != NULL)
{
if (strcmp(current->name, name) == 0)
return current;
current = current->next;
}
return NULL;
}
void AddAlias(const char *name, const char *value)
{
alias_t *existing = FindAlias(name);
if (existing)
{
free(existing->value);
existing->value = strdup(value);
return;
}
alias_t *new_alias = malloc(sizeof(alias_t));
new_alias->name = strdup(name);
new_alias->value = strdup(value);
new_alias->next = aliases;
aliases = new_alias;
}
int ReadAliases(const char *filename)
{
FILE *file = fopen(filename, "r");
if (!file)
return -1;
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1)
{
if (line[read - 1] == '\n')
line[read - 1] = '\0';
char *eq = strchr(line, '=');
if (!eq)
continue;
*eq = '\0';
AddAlias(line, eq + 1);
}
free(line);
fclose(file);
return 0;
}
int WriteAliases(const char *filename)
{
FILE *file = fopen(filename, "w");
if (!file)
{
perror("Error writing aliases");
return -1;
}
alias_t *current = aliases;
while (current)
{
fprintf(file, "%s=%s\n", current->name, current->value);
current = current->next;
}
fclose(file);
return 0;
}
char *QuoteValue(const char *value)
{
size_t quotes = 0;
for (const char *p = value; *p; p++)
{
if (*p == '\'')
quotes++;
}
char *quoted = malloc(strlen(value) + quotes * 4 + 3);
if (!quoted)
return NULL;
char *dest = quoted;
*dest++ = '\'';
for (const char *p = value; *p; p++)
{
if (*p == '\'')
{
strcpy(dest, "'\\''");
dest += 4;
}
else
*dest++ = *p;
}
*dest++ = '\'';
*dest = '\0';
return quoted;
}
int main(int argc, char *argv[])
{
const char *home = getenv("HOME");
if (!home)
{
fprintf(stderr, "alias: HOME not set\n");
return 2;
}
char path[1024];
snprintf(path, sizeof(path), "%s/.aliases", home);
if (ReadAliases(path) == -1 && errno != ENOENT)
{
perror("Error reading aliases");
return 2;
}
int status = 0;
if (argc == 1)
{
alias_t *current = aliases;
while (current)
{
char *q = QuoteValue(current->value);
printf("alias %s=%s\n", current->name, q);
free(q);
current = current->next;
}
}
else
{
for (int i = 1; i < argc; i++)
{
char *arg = argv[i];
char *eq = strchr(arg, '=');
if (eq)
{
*eq = '\0';
char *name = arg;
char *value = eq + 1;
AddAlias(name, value);
char *q = QuoteValue(value);
printf("alias %s=%s\n", name, q);
free(q);
}
else
{
alias_t *a = FindAlias(arg);
if (a)
{
char *q = QuoteValue(a->value);
printf("alias %s=%s\n", a->name, q);
free(q);
}
else
{
fprintf(stderr, "alias: %s: not found\n", arg);
status = 1;
}
}
}
}
if (WriteAliases(path) == -1)
status = 1;
FreeAliases();
return status;
}