BarryServer : Git

All the code for all my projects
// BarryServer : Git / OrionUserland / commit / 19aefaad8af9de8719ba1e5b5340e0a1b9c68853 / ls / main.c

// Related

OrionUserland

Barry Importing existing Orion Userland 19aefaa (2 years, 4 months ago)
diff --git a/ls/main.c b/ls/main.c
new file mode 100644
index 0000000..27b754c
--- /dev/null
+++ b/ls/main.c
@@ -0,0 +1,320 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <dirent.h>
+#include <termios.h>
+#include <pwd.h>
+#include <grp.h>
+
+char *progname;
+#include "arg.h"
+
+Winsize termsz;
+int allFlag = 0;
+int longFlag = 0;
+
+/* Structure for a result */
+typedef struct Result Result;
+struct Result {
+	Result *next, *prev;
+	ino_t ino;
+	enum DirType type;
+	size_t namelen;
+	char name[255];
+	Stat stat;
+};
+
+/* Compare results by name */
+static int
+compare_name(Result *a, Result *b)
+{
+	return (strcmp(a->name, b->name) < 0);
+}
+
+/* Compare results by type */
+static int
+compare_type(Result *a, Result *b)
+{
+	return (a->type == DT_DIR && b->type != DT_DIR);
+}
+
+/* Sort a list of results */
+static Result *
+sort_results(Result *head, int (*compare)(Result *, Result *))
+{
+	Result *curr, *shead = NULL, *slast, *scurr;
+	int i, len = 0;
+	for (curr = head; curr; curr = curr->next)
+		len++;
+
+	/* Sort */
+	for (i = 0; i < len; i++) {
+		scurr = head;
+		for (curr = head->next; curr; curr = curr->next) {
+			if (compare(curr, scurr))
+				scurr = curr;
+		}
+
+		/* Unlink from old list */
+		if (scurr == head)
+			head = scurr->next;
+		if (scurr->next)
+			scurr->next->prev = scurr->prev;
+		if (scurr->prev)
+			scurr->prev->next = scurr->next;
+		scurr->prev = scurr->next = NULL;
+
+		/* Add to sorted list */
+		if (!shead) {
+			shead = scurr;
+		} else {
+			scurr->prev = slast;
+			slast->next = scurr;
+		}
+		slast = scurr;
+	}
+
+	return shead;
+}
+
+/* Print normal results */
+static void
+print_normal(Result *head)
+{
+	Result *curr, *next, *prev;
+	size_t printed = 0;
+
+	for (curr = head; curr; curr = next) {
+		prev = curr->prev;
+		next = curr->next;
+
+		int executable = 0;
+		if ((curr->stat.mode & S_IXUSR)
+		 || (curr->stat.mode & S_IXGRP)
+		 || (curr->stat.mode & S_IXOTH))
+			executable = 1;
+
+		if (curr->type == DT_DIR)
+			printf("\033[1;34m%s\033[0m  ", curr->name);
+		else if (curr->type == DT_CHR || curr->type == DT_BLK)
+			printf("\033[1;33m%s\033[0m  ", curr->name);
+		else if (curr->type == DT_LNK)
+			printf("\033[1;36m%s\033[0m  ", curr->name);
+		else if (curr->type == DT_REG && executable)
+			printf("\033[1;32m%s\033[0m  ", curr->name);
+		else
+			printf("%s  ", curr->name);
+		printed++;
+
+		/* Remove from list */
+		if (prev)
+			prev->next = next;
+		if (next)
+			next->prev = prev;
+		if (curr == head)
+			head = next;
+		free(curr);
+	}
+	if (printed)
+		putchar('\n');
+}
+
+/* Print long results */
+static void
+print_long(Result *head)
+{
+	Result *curr, *next, *prev;
+	size_t printed = 0;
+
+	/* Find max column widths */
+	size_t total = 0;
+	int linkWidth = 0, unameWidth = 0, groupWidth = 0, sizeWidth = 0;
+	for (curr = head; curr; curr = curr->next) {
+		int linkTmp = curr->stat.nlink, linkWidthTmp = 1;
+		while (linkTmp /= 10)
+			linkWidthTmp++;
+		if (linkWidthTmp > linkWidth)
+			linkWidth = linkWidthTmp;
+
+		Passwd *pwd = getpwuid(curr->stat.uid);
+		if (strlen(pwd->username) > unameWidth)
+			unameWidth = strlen(pwd->username);
+		Group *grp = getgrgid(curr->stat.gid);
+		if (strlen(grp->name) > groupWidth)
+			groupWidth = strlen(grp->name);
+
+		int sizeTmp = curr->stat.size, sizeWidthTmp = 1;
+		while (sizeTmp /= 10)
+			sizeWidthTmp++;
+		if (sizeWidthTmp > sizeWidth)
+			sizeWidth = sizeWidthTmp;
+
+		total += (curr->stat.size + (1024 - 1)) / 1024;
+	}
+
+	/* Print out */
+	printf("total %d\n", total);
+	for (curr = head; curr; curr = next) {
+		prev = curr->prev;
+		next = curr->next;
+
+		char perm[] = "----------";
+		char type[] = "?-dcbfsl";
+		char uname[33], group[33];
+		int executable = 0;
+		perm[0] = type[curr->type];
+		perm[1] = (curr->stat.mode & S_IRUSR) ? 'r' : '-';
+		perm[2] = (curr->stat.mode & S_IWUSR) ? 'w' : '-';
+		perm[3] = (curr->stat.mode & S_IXUSR) ? 'x' : '-';
+		perm[4] = (curr->stat.mode & S_IRGRP) ? 'r' : '-';
+		perm[5] = (curr->stat.mode & S_IWGRP) ? 'w' : '-';
+		perm[6] = (curr->stat.mode & S_IXGRP) ? 'x' : '-';
+		perm[7] = (curr->stat.mode & S_IROTH) ? 'r' : '-';
+		perm[8] = (curr->stat.mode & S_IWOTH) ? 'w' : '-';
+		perm[9] = (curr->stat.mode & S_IXOTH) ? 'x' : '-';
+		Passwd *pwd = getpwuid(curr->stat.uid);
+		Group *grp = getgrgid(curr->stat.gid);
+		if ((curr->stat.mode & S_IXUSR)
+		 || (curr->stat.mode & S_IXGRP)
+		 || (curr->stat.mode & S_IXOTH))
+			executable = 1;
+
+		printf("%s %*d %*s %*s %*d ", perm,
+		       linkWidth, curr->stat.nlink,
+		       -unameWidth, pwd->username,
+		       -groupWidth, grp->name,
+		       sizeWidth, curr->stat.size);
+
+		if (curr->type == DT_DIR)
+			printf("\033[1;34m%s\033[0m\n", curr->name);
+		else if (curr->type == DT_CHR || curr->type == DT_BLK)
+			printf("\033[1;33m%s\033[0m\n", curr->name);
+		else if (curr->type == DT_LNK)
+			printf("\033[1;36m%s\033[0m\n", curr->name);
+		else if (curr->type == DT_REG && executable)
+			printf("\033[1;32m%s\033[0m\n", curr->name);
+		else
+			printf("%s\n", curr->name);
+		printed++;
+
+		/* Remove from list */
+		if (prev)
+			prev->next = next;
+		if (next)
+			next->prev = prev;
+		if (curr == head)
+			head = next;
+		free(curr);
+	}
+}
+
+/* List files in a directory */
+static void
+ls(char *name)
+{
+	int fd, sz, i;
+	char *buf, cwd[1024];
+	struct stat statbuf;
+	struct dirent *de;
+
+	Result *head = NULL, *prev = NULL, *next, *curr;
+	size_t len = 0, longest = 0;
+
+	fd = open(name, O_RDONLY);
+	if (fd < 0) {
+		printf("%s: %s: ", progname, name);
+		perror(NULL);
+		return;
+	}
+
+	stat(name, &statbuf);
+	if (!S_ISDIR(statbuf.mode)) {
+		close(fd);
+		return;
+	}
+
+	getcwd(cwd, 1024);
+	chdir(name);
+
+	/* Get Directory Entries */
+	buf = malloc(512);
+	sz = getdents(fd, buf, 512);
+	for (de = (void *) buf;
+	     de < (struct dirent *) (buf + sz);
+	     de = (void *) de + de->namelen + sizeof(struct dirent)) {
+		if (de->name[0] == '.' && !allFlag)
+			continue;
+		curr = malloc(sizeof(Result));
+		curr->next = NULL;
+		curr->prev = prev;
+		curr->ino = de->ino;
+		curr->type = de->type;
+		curr->namelen = de->namelen;
+		memcpy(curr->name, de->name, de->namelen);
+		curr->name[de->namelen] = '\0';
+		stat(curr->name, &curr->stat);
+		if (prev)
+			prev->next = curr;
+		else
+			head = curr;
+		prev = curr;
+		len++;
+
+		if (longest < curr->namelen)
+			longest = curr->namelen;
+	}
+	free(buf);
+	close(fd);
+
+	head = sort_results(head, compare_name);
+	head = sort_results(head, compare_type);
+
+	if (longFlag)
+		print_long(head);
+	else
+		print_normal(head);
+
+	chdir(cwd);
+}
+
+/* Main function */
+int
+main(int argc, char *argv[])
+{
+	int i;
+	ioctl(STDOUT_FILENO, TCGWINSZ, &termsz);
+
+	ARGBEGIN {
+	case 'a':
+		allFlag = 1;
+		break;
+	case 'l':
+		longFlag = 1;
+		break;
+	default:
+		printf("Usage:\n");
+	} ARGEND;
+
+	if (argc == 0) {
+		ls(".");
+		return 0;
+	}
+
+	if (argc == 1) {
+		ls(argv[0]);
+		return 0;
+	}
+
+	for (i = 0; i < argc; i++) {
+		printf("%s:\n", argv[i]);
+		ls(argv[i]);
+		if (i < argc-1)
+			printf("\n");
+	}
+
+	return 0;
+}