aboutsummaryrefslogtreecommitdiff
path: root/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'ls.c')
-rw-r--r--ls.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/ls.c b/ls.c
new file mode 100644
index 0000000..c3a2095
--- /dev/null
+++ b/ls.c
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (C) 2022, 2023 Ferass El Hafidi <vitali64pmemail@protonmail.com>
+ * Copyright (C) 2022 Leah Rowe <leah@libreboot.org>
+ */
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <sys/ioctl.h>
+
+#define REQ_PRINT_USAGE /* Require print_usage() from common.h */
+#define REQ_ERRPRINT /* Require errprint() from common.h */
+#define DESCRIPTION "Print <directory>'s contents to standard output.\
+ If no directory is specified, print the current directory's contents."
+#define OPERANDS "[-1aACimlpgno] [directory]"
+#include "common.h"
+
+char *argv0;
+char param[256];
+int ls(char *path);
+void printUsage(char *params);
+
+#ifdef FASESBOX
+int ls_main(int argc, char *argv[]) {
+#else
+int main(int argc, char *argv[]) {
+#endif
+ int status = 0;
+ int success = 0;
+ int argument, i;
+ argv0 = strdup(argv[0]);
+ for (i=0; i<256; i++) {
+ param[i]=0;
+ }
+
+ while ((argument = getopt(argc, argv, OPERANDS)) != -1) {
+ if (argument == '?') {
+ print_usage(argv[0], DESCRIPTION, OPERANDS, VERSION);
+ return 1;
+ }
+ param[argument] = argument;
+
+ if (argument=='C') {
+ param['1'] = 0;
+ param['m'] = 0;
+ }
+ else if (argument=='1' || argument=='g' || argument=='n') {
+ param['m'] = 0;
+ param['C'] = 0;
+ }
+ else if (argument=='m') {
+ param['1'] = 0;
+ param['C'] = 0;
+ }
+ if (argument=='o' || argument=='n' || argument=='g') {
+ param['l'] = 'l';
+ }
+ } argc -= optind; argv += optind;
+ if (status) {
+ if(!param['1']) printf("\n");
+ return status;
+ }
+
+ if (!param['C'] && !param['m'] && !param['1'])
+ param['1'] = '1';
+
+ if (param['l'] || param['g']) {
+ param['m'] = 0;
+ param['C'] = 0;
+ param['1'] = '1';
+ }
+
+ for (i = 0; i < argc; i++) {
+ if ((success |= (argv[i][0] != '-' ? 1 : 0))) {
+ if (!strcmp(argv[i],".")) status |= ls("./");
+ else status |= ls(argv[i]);
+ }
+ }
+
+ i = success ? status : ls("./");
+ if (!param['1'])
+ printf("\n");
+
+ return i;
+}
+
+int ls(char *path) {
+ int file, dotname, cwdname, prevdir, dot;
+ long unsigned int cols_used;
+ DIR *directory;
+ struct stat file_status;
+ struct dirent *dirtree;
+ struct winsize columns;
+ char *name, file_moddate[256];
+ char file_modes[] = "----------";
+ directory = opendir(path);
+
+ if (param['C']) {
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &columns);
+ cols_used = 0;
+ }
+
+ if (directory == NULL) {
+ file = open(path, O_RDONLY);
+ if (file == -1) return errprint(argv0, path, errno);
+ printf("%s\n", path);
+ if (close(file) == -1)
+ return errprint(argv0, path, errno);
+ }
+
+ while ((dirtree = readdir(directory)) != NULL) {
+ name = dirtree->d_name;
+
+ cwdname = strcmp(name, ".") ? 0 : 1;
+ prevdir = strcmp(name, "..") ? 0 : 1;
+ dotname = (name[0]=='.' && !cwdname && !prevdir) ? 1 : 0;
+ dot = dotname | prevdir | cwdname;
+
+ if (dot && !param['a'] && !param['A']) continue;
+ if ((cwdname || prevdir) && param['A']) continue;
+
+ if (param['i']) printf("%llu ", (unsigned long long)dirtree->d_ino);
+ if (param['l']) {
+ char *fullpath = malloc(strlen(path) + strlen(name) + 2);
+ if (fullpath) {
+ strcpy(fullpath, path);
+ if (path[strlen(path) - 1] != '/') strcat(fullpath, "/");
+ strcat(fullpath, name);
+ }
+ lstat(fullpath, &file_status);
+ /* File modes */
+ /* File type */
+ {
+ if (S_ISBLK(file_status.st_mode)) file_modes[0] = 'b';
+ else if (S_ISCHR(file_status.st_mode)) file_modes[0] = 'c';
+ else if (S_ISDIR(file_status.st_mode)) file_modes[0] = 'd';
+ else if (S_ISFIFO(file_status.st_mode)) file_modes[0] = 'p';
+ else if (S_ISREG(file_status.st_mode)) file_modes[0] = '-';
+ else if (S_ISLNK(file_status.st_mode)) file_modes[0] = 'l';
+ else file_modes[0] = 's';
+ }
+ /* User */
+ {
+ if (file_status.st_mode & S_IRUSR) file_modes[1] = 'r';
+ if (file_status.st_mode & S_IWUSR) file_modes[2] = 'w';
+ if (file_status.st_mode & S_IXUSR) file_modes[3] = 'x';
+ }
+ /* Group */
+ {
+ if (file_status.st_mode & S_IRGRP) file_modes[4] = 'r';
+ if (file_status.st_mode & S_IWGRP) file_modes[5] = 'w';
+ if (file_status.st_mode & S_IXGRP) file_modes[6] = 'x';
+ }
+ /* Others */
+ {
+ if (file_status.st_mode & S_IROTH) file_modes[7] = 'r';
+ if (file_status.st_mode & S_IWOTH) file_modes[8] = 'w';
+ if (file_status.st_mode & S_IXOTH) file_modes[9] = 'x';
+ }
+ printf("%s ", file_modes);
+ /* Number of links */
+ printf("%lu ", (long unsigned int)file_status.st_nlink);
+ /* Owner name/uid */
+ if (!param['g'])
+ /* This recursiveness is needed for whatever reason,
+ * else it doesn't work...
+ */
+ if (!param['n'])
+ printf("%s ", getpwuid(file_status.st_uid)->pw_name);
+ if (param['n']) printf("%u ", file_status.st_uid);
+ /* Group name/gid */
+ if (!param['o'])
+ if (!param['n']) printf("%s ", getgrgid(file_status.st_gid)->gr_name);
+ if (param['n']) printf("%u ", file_status.st_gid);
+ /* Size of file */
+ printf("%llu ", (unsigned long long)file_status.st_size);
+ /* Date and time */
+ int strftime_status = strftime(file_moddate, sizeof(file_moddate),
+ "%b %e %H:%MM", localtime(&file_status.st_mtime));
+ /* It should be st_mtim right? */
+ file_moddate[strlen(file_moddate) - 1] = 0; /* Remove newline */
+ printf("%s ", strftime_status ? file_moddate : "<strftime() returned 0>");
+ free(fullpath);
+ }
+ printf("%s", name);
+ if (param['p']) {
+ char *fullpath = malloc(strlen(path) + strlen(name) + 2);
+ if (fullpath) {
+ strcpy(fullpath, path);
+ if (path[strlen(path) - 1] != '/') strcat(fullpath, "/");
+ strcat(fullpath, name);
+ }
+ stat(fullpath, &file_status);
+ if (S_ISDIR(file_status.st_mode)) printf("/");
+ free(fullpath);
+ }
+ if (param['C']) {
+ if (cols_used < (long unsigned int)((columns.ws_col) / 12)) {
+ for (long unsigned int i = strlen(name); i < 11; i++) printf(" ");
+ cols_used++;
+ }
+ if (cols_used == (long unsigned int)((columns.ws_col) / 12)) {
+ printf("\n");
+ cols_used = 0;
+ }
+ }
+ else if (param['1'])
+ printf("\n");
+ else if (param['m'])
+ printf(", ");
+ }
+ closedir(directory);
+
+ return errprint(argv0, path, errno);
+}