OrionUserland
Barry Importing existing Orion Userland 19aefaa (3 years, 2 months ago)
diff --git a/ls/Makefile b/ls/Makefile
new file mode 100644
index 0000000..5254c7c
--- /dev/null
+++ b/ls/Makefile
@@ -0,0 +1,46 @@
+PRODUCT=$(notdir $(abspath $(CURDIR)))
+
+CC=i686-orion-gcc
+CFLAGS=
+
+AS=i686-orion-as
+AFLAGS=
+
+LD=i686-orion-gcc
+LFLAGS=
+
+AS_SOURCES := $(shell find . -name '*.S')
+OBJS = $(sort $(subst ./,build/,$(subst .S,.o,$(AS_SOURCES))))
+
+C_SOURCES := $(shell find . -name '*.c')
+OBJS += $(sort $(subst ./,build/,$(subst .c,.o,$(C_SOURCES))))
+
+.PHONY: clean all install
+
+all: $(PRODUCT)
+
+clean:
+ @echo "REMOVING OBJECT FILES"
+ @mkdir -p build
+ @rm -rf build
+ @touch $(PRODUCT)
+ @rm $(PRODUCT)
+
+install: $(PRODUCT)
+ @echo "INSTALLING $^"
+ @mkdir -p ${SYSROOT}/bin/
+ @install -Dm 755 $(PRODUCT) -t ${SYSROOT}/bin/
+
+$(PRODUCT): $(OBJS)
+ @echo "LINKING $@"
+ @$(LD) -o $@ $^ $(LFLAGS)
+
+build/%.o: %.c
+ @echo "COMPILING $<"
+ @mkdir -p $(@D)
+ @$(CC) -c $< -o $@ $(CFLAGS)
+
+build/%.o: %.S
+ @echo "ASSEMBLING $<"
+ @mkdir -p $(@D)
+ @$(AS) $< -o $@ $(AFLAGS)
diff --git a/ls/arg.h b/ls/arg.h
new file mode 100644
index 0000000..9022339
--- /dev/null
+++ b/ls/arg.h
@@ -0,0 +1,42 @@
+#ifndef ARG_H
+#define ARG_H
+
+extern char *progname;
+
+#define ARGBEGIN for (progname = *argv, argv++, argc--; \
+ argc && argv[0] && argv[0][0] == '-' \
+ && argv[0][1]; \
+ argc--, argv++) { \
+ char argc_, **argv_; \
+ int brk_; \
+ if (argv[0][1] == '-' && argv[0][2] == '\0') { \
+ argv++; \
+ argc--; \
+ break; \
+ } \
+ int i_; \
+ for (i_ = 1, brk_ = 0, argv_ = argv; \
+ argv[0][i_] && !brk_; \
+ i_++) { \
+ if (argv_ != argv) \
+ break; \
+ argc_ = argv[0][i_]; \
+ switch (argc_)
+#define ARGEND } \
+ }
+
+#define ARGC() argc_
+
+#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL) ? \
+ ((x), abort(), (char *) 0) : \
+ (brk_ = 1, (argv[0][i_+1] != '\0') ? \
+ (&argv[0][i_+1]) : \
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL) ? \
+ (char *) 0 : \
+ (brk_ = 1, (argv[0][i_+1] != '\0') ? \
+ (&argv[0][i_+1]) : \
+ (argc--, argv++, argv[0])))
+
+#endif
diff --git a/ls/ls b/ls/ls
new file mode 100755
index 0000000..0921d86
Binary files /dev/null and b/ls/ls differ
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;
+}