127 lines
3.3 KiB
C
127 lines
3.3 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#define MAX_PATH_SIZE 512
|
||
|
#define SEGMENT_LENGTH 2
|
||
|
#define LAST_SEGMENT_MAX_LENGTH 16
|
||
|
#define MAX_SEGMENTS_AMOUNT 64
|
||
|
|
||
|
typedef struct {
|
||
|
size_t seperator;
|
||
|
size_t length;
|
||
|
} Segment;
|
||
|
|
||
|
/// @returns Amount of segments
|
||
|
size_t get_path_segments(
|
||
|
Segment* dest,
|
||
|
size_t dest_size,
|
||
|
const char* path,
|
||
|
size_t path_length)
|
||
|
{
|
||
|
size_t dest_i = 0;
|
||
|
size_t i = 0;
|
||
|
while (i < path_length) {
|
||
|
size_t seperator = i;
|
||
|
i += 1;
|
||
|
while (path[i] != '\0' && path[i] != '/') {
|
||
|
i += 1;
|
||
|
}
|
||
|
size_t length = i - seperator - 1;
|
||
|
dest[dest_i] = (Segment) { seperator, length };
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
return dest_i;
|
||
|
}
|
||
|
|
||
|
bool in_home_directory(
|
||
|
const char* path,
|
||
|
const Segment* segments,
|
||
|
size_t segments_length,
|
||
|
const char* username)
|
||
|
{
|
||
|
if (segments_length < 2)
|
||
|
return false;
|
||
|
if (strncmp(&path[segments[0].seperator + 1], "home", segments[0].length) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
if (strncmp(&path[segments[1].seperator + 1], username, strlen(username)) != 0) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
char cwd_path[MAX_PATH_SIZE] = "";
|
||
|
if (getcwd(cwd_path, sizeof(cwd_path)) == NULL) {
|
||
|
fprintf(stderr, "error: failed to get current working directory: %s\n", strerror(errno));
|
||
|
exit(1);
|
||
|
}
|
||
|
const size_t cwd_path_length = strlen(cwd_path);
|
||
|
|
||
|
const char* username = getlogin();
|
||
|
|
||
|
Segment segments[MAX_SEGMENTS_AMOUNT] = { 0 };
|
||
|
size_t segments_length = get_path_segments(
|
||
|
segments,
|
||
|
sizeof(segments) / sizeof(segments[0]),
|
||
|
cwd_path,
|
||
|
cwd_path_length);
|
||
|
|
||
|
bool in_home_dir = in_home_directory(cwd_path, segments, segments_length, username);
|
||
|
|
||
|
char short_path[MAX_PATH_SIZE] = "";
|
||
|
|
||
|
size_t segments_i = 0;
|
||
|
size_t dest_i = 0;
|
||
|
|
||
|
if (in_home_dir) {
|
||
|
short_path[dest_i] = '~';
|
||
|
dest_i += 1;
|
||
|
segments_i += 2;
|
||
|
}
|
||
|
|
||
|
for (; segments_i < segments_length - 1; segments_i += 1) {
|
||
|
short_path[dest_i] = '/';
|
||
|
dest_i += 1;
|
||
|
Segment* segment = &segments[segments_i];
|
||
|
for (size_t i = 0; i < segment->length && i < SEGMENT_LENGTH; i += 1) {
|
||
|
short_path[dest_i] = cwd_path[segment->seperator + 1 + i];
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(segments_length == 2 && in_home_dir)) {
|
||
|
short_path[dest_i] = '/';
|
||
|
dest_i += 1;
|
||
|
Segment* last = &segments[segments_i];
|
||
|
if (last->length >= LAST_SEGMENT_MAX_LENGTH) {
|
||
|
for (size_t i = 0; i < 5; i += 1) {
|
||
|
short_path[dest_i] = cwd_path[last->seperator + 1 + i];
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
for (size_t i = 0; i < 3; i += 1) {
|
||
|
short_path[dest_i] = '.';
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
for (size_t i = 0; i < 8; i += 1) {
|
||
|
short_path[dest_i] = cwd_path[last->seperator + 1 + last->length - 8 + i];
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
} else {
|
||
|
for (size_t i = 0; i < last->length; i += 1) {
|
||
|
short_path[dest_i] = cwd_path[last->seperator + 1 + i];
|
||
|
dest_i += 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
short_path[dest_i] = '\0';
|
||
|
|
||
|
fputs(short_path, stdout);
|
||
|
}
|
||
|
|