You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
3.9 KiB
161 lines
3.9 KiB
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <linux/limits.h>
|
|
|
|
#include "ansi-colour.h"
|
|
#include "version.h"
|
|
|
|
/*
|
|
ls - print all files and directories in working directory
|
|
Available arguments:
|
|
--help: show this help message
|
|
--version: show the version of the program (WIP)
|
|
*/
|
|
//https://stackoverflow.com/questions/4770985/how-to-check-if-a-string-starts-with-another-string-in-c/4770992#4770992
|
|
bool startsWithChar(const char *pre, const char str) {
|
|
char *e;
|
|
int index;
|
|
e = strchr(pre, str);
|
|
index = (int)(e - pre);
|
|
return index == 0;
|
|
}
|
|
|
|
int cmp(const void *a, const void *b){
|
|
return strcmp(*(const char **)a, *(const char **)b);
|
|
}
|
|
|
|
//https://stackoverflow.com/a/4553076
|
|
bool isRegularFile(const char *path)
|
|
{
|
|
struct stat path_stat;
|
|
stat(path, &path_stat);
|
|
return S_ISREG(path_stat.st_mode);
|
|
}
|
|
|
|
int printBool(bool cond) {
|
|
printf("%s\n", cond ? "true" : "false");
|
|
return 0;
|
|
}
|
|
|
|
//lots o' code ~~stolen~~ borrowed from https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html
|
|
int main(int argc, char** argv) {
|
|
//define default options
|
|
bool colour = false;
|
|
bool showdot = false;
|
|
bool specpath = false;
|
|
bool columns = false;
|
|
char *thatpath;
|
|
for (int i = 1; i < argc; i++) {
|
|
char* arg = argv[i];
|
|
/*printf(arg);
|
|
printf(" ");*/
|
|
if (!strcmp(arg, "--help")) {
|
|
char* help =
|
|
"Drake's Epic Coreutils (working title) "
|
|
DRAKECU_VERSION
|
|
"\n"
|
|
"ls - print all files and directories in working directory\n"
|
|
"Available arguments:\n"
|
|
" --help: show this help message\n"
|
|
" --version: show the version of the program\n"
|
|
" --color: colour the output depending on whether there is a file or folder\n"
|
|
" --colour: same as --color, but for our Bri'ish folks\n"
|
|
" -C, --columns: print every entry on a seperate line";
|
|
printf("%s\n", help);
|
|
return 0;
|
|
} else if (!strcmp(arg, "--version")) {
|
|
printf(DRAKECU_VERSION);
|
|
return 0;
|
|
} else if (!strcmp(arg, "--color") || !strcmp(arg, "--colour")) {
|
|
colour = true;
|
|
} else if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) {
|
|
showdot = true;
|
|
} else if (!strcmp(arg, "-C") || !strcmp(arg, "--columns")) {
|
|
columns = true;
|
|
} else {
|
|
//TODO: interpret absolute *and* relative paths. can't be that hard, right?
|
|
specpath = true;
|
|
thatpath = arg;
|
|
}
|
|
}
|
|
char wd[PATH_MAX];
|
|
if (specpath == false) {
|
|
getcwd(wd, sizeof(wd));
|
|
} else if (specpath == true) {
|
|
char *e = realpath(thatpath, NULL);
|
|
strcpy(wd, e);
|
|
free(e);
|
|
}
|
|
//printf(wd);
|
|
DIR* dirp;
|
|
struct dirent *dp;
|
|
dirp = opendir(wd);
|
|
if (dirp == NULL) {
|
|
printf("couldn't open '%s'\n", wd);
|
|
return 1;
|
|
}
|
|
int len = sizeof(char);
|
|
char *out = malloc(len);
|
|
out = NULL;
|
|
dp = readdir(dirp);
|
|
do {
|
|
char* dirname = dp->d_name;
|
|
if (!startsWithChar(dirname, '.') || showdot == true) {
|
|
len += 1 + strlen(dirname) + strlen("§");
|
|
out = realloc(out, len);
|
|
strcat(out, dirname);
|
|
strcat(out, "§");
|
|
}
|
|
} while ((dp = readdir(dirp)) != NULL);
|
|
free(dirp);
|
|
char *word, *words[strlen(out)/2+1];
|
|
int i,n;
|
|
i=0;
|
|
word = strtok(out, "§");
|
|
while (word != NULL) {
|
|
words[i++] = word;
|
|
word = strtok(NULL, "§");
|
|
}
|
|
n = i;
|
|
qsort(words, n, sizeof(*words), cmp);
|
|
char oldwd[PATH_MAX];
|
|
strcpy(oldwd, wd);
|
|
int maxLen = 0;
|
|
if (columns == false) {
|
|
maxLen = 180;
|
|
}
|
|
int currLen = 0;
|
|
for (i = 0; i < n; i++) {
|
|
if (colour == false) {
|
|
printf("%s ", words[i]);
|
|
} else {
|
|
strcpy(wd, oldwd);
|
|
strcat(wd, "/");
|
|
strcat(wd, words[i]);
|
|
//printf(wd);
|
|
if (isRegularFile(wd) == false) {
|
|
printf(ANSI_BLUE);
|
|
printf("%s ", words[i]);
|
|
printf(ANSI_RESET);
|
|
} else {
|
|
printf("%s ", words[i]);
|
|
}
|
|
}
|
|
currLen += strlen(words[i]);
|
|
if (currLen >= maxLen) {
|
|
printf("\n");
|
|
currLen = 0;
|
|
}
|
|
}
|
|
free(out);
|
|
return 0;
|
|
}
|