Last active
December 18, 2017 20:15
-
-
Save Cranc/2de61c7d0b405795a71dfafb93417b74 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: myls.h | |
* Author: dennis | |
* | |
* Created on December 16, 2017, 3:44 PM | |
*/ | |
#ifndef MYLS_H | |
#define MYLS_H | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#define ANSI_COLOR_RED "\x1b[31m" | |
#define ANSI_COLOR_GREEN "\x1b[32m" | |
#define ANSI_COLOR_YELLOW "\x1b[33m" | |
#define ANSI_COLOR_BLUE "\x1b[34m" | |
#define ANSI_COLOR_MAGENTA "\x1b[35m" | |
#define ANSI_COLOR_CYAN "\x1b[36m" | |
#define ANSI_COLOR_RESET "\x1b[0m" | |
#define FILEINFOLENGTH 400 | |
#define MAXARGUMENTS 20 | |
#define OPTIONCOUNT 2 | |
#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct)) | |
static int toggle = 0; | |
typedef enum{ | |
No = 0, | |
Allhidden, | |
Listlong | |
} options; | |
typedef struct { char key; int val; } t_symstruct; | |
static t_symstruct lookuptable[] = { | |
{ 'a', Allhidden }, | |
{ 'l', Listlong } | |
}; | |
void printToScreen(char* in, int targetStrLen); | |
int getCurrentWorkingDirectory(char* path, int size); | |
void initOptions(options *arr, int size); | |
int getOptions(int argc, char** argv, options *arr, int size); | |
int addToList(options *arr, int size, options val); | |
int listContains(options *arr, int size, options val); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif /* MYLS_H */ | |
/* | |
* File: myls.c | |
* Author: dennis | |
* | |
* Created on December 16, 2017, 3:40 PM | |
*/ | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <limits.h> | |
#include <dirent.h> | |
#include <errno.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <pwd.h> | |
#include <grp.h> | |
#include <time.h> | |
#include "myls.h" | |
/* | |
* | |
*/ | |
int main(int argc, char** argv) { | |
options args[OPTIONCOUNT]; | |
char path[PATH_MAX]; | |
DIR *directory; | |
struct dirent *dp; | |
int res = 0; | |
int option_value = 0; | |
//get path | |
if(argc <= 1) | |
res = getCurrentWorkingDirectory(path, PATH_MAX); | |
if(argc > 1){ | |
//if not flag has to be path! | |
if(argv[1][0] != '-'){ | |
strncpy(path, argv[1], PATH_MAX); | |
} else { | |
res = getCurrentWorkingDirectory(path, PATH_MAX); | |
} | |
} | |
if(res == -1){ | |
printf(ANSI_COLOR_RED"Error getting current working directory"ANSI_COLOR_RESET); | |
return -1; | |
} | |
printf(ANSI_COLOR_GREEN"Path: %s\n"ANSI_COLOR_RESET,path); | |
//get all the options | |
initOptions(args, OPTIONCOUNT); | |
res = getOptions(argc, argv, args, OPTIONCOUNT); | |
if(res == -1){ | |
printf(ANSI_COLOR_RED "Error getting Options\n" ANSI_COLOR_RESET); | |
return res; | |
} | |
if(res == 1) | |
printf(ANSI_COLOR_YELLOW "A non argument was detected and will be ignored\n" ANSI_COLOR_RESET); | |
//start working | |
directory = opendir(path); | |
if(directory == NULL) | |
printf(ANSI_COLOR_RED"Error opening the directory [%s]\n"ANSI_COLOR_RESET,strerror(errno)); | |
errno = ENOENT; | |
while ((dp = readdir (directory)) != NULL) { | |
char file_info[FILEINFOLENGTH]; | |
memset(file_info,0,FILEINFOLENGTH); | |
int hidden = 0; | |
if (dp->d_name[0] == '.' || dp->d_name[strlen(dp->d_name)-1] == '~') | |
hidden = 1; | |
if(hidden == 1 && listContains(args, OPTIONCOUNT, Allhidden) == 0) | |
continue; | |
if(listContains(args, OPTIONCOUNT, Listlong) == 1){ | |
struct stat sb; | |
if (lstat(dp->d_name, &sb) == -1) { | |
printf(ANSI_COLOR_RED"Error opening the directory [%s]\n"ANSI_COLOR_RESET,strerror(errno)); | |
return -1; | |
} | |
//permissions | |
if(S_ISDIR(sb.st_mode)) | |
strncat(file_info,"d",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IRUSR) | |
strncat(file_info,"r",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IWUSR) | |
strncat(file_info,"w",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IXUSR) | |
strncat(file_info,"x",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IRGRP) | |
strncat(file_info,"r",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IWGRP) | |
strncat(file_info,"w",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IXGRP) | |
strncat(file_info,"x",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IROTH) | |
strncat(file_info,"r",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IWOTH) | |
strncat(file_info,"w",1); | |
else | |
strncat(file_info,"-",1); | |
if(sb.st_mode & S_IXOTH) | |
strncat(file_info,"x",1); | |
else | |
strncat(file_info,"-",1); | |
printToScreen(file_info, 10); | |
memset(file_info,0,FILEINFOLENGTH); | |
//file type | |
switch (sb.st_mode & S_IFMT) { | |
case S_IFBLK: strncat(file_info,"block dev",9); break;//block device | |
case S_IFCHR: strncat(file_info,"char dev",8); break;//character device | |
case S_IFDIR: strncat(file_info,"directory",9); break;//directory | |
case S_IFIFO: strncat(file_info,"pipe",4); break;//fifo pipe | |
case S_IFLNK: strncat(file_info,"symlink",7); break;//symlink | |
case S_IFREG: strncat(file_info,"file",4); break;//file | |
case S_IFSOCK: strncat(file_info,"socket",6); break;//socket | |
default: strncat(file_info,"unknown",7); break;//unknown | |
} | |
printToScreen(file_info, 9); | |
memset(file_info,0,FILEINFOLENGTH); | |
//owner and group | |
register struct passwd *pw; | |
pw = getpwuid (sb.st_uid); | |
strncat(file_info,pw->pw_name,strlen(pw->pw_name)); | |
printToScreen(file_info, 0); | |
memset(file_info,0,FILEINFOLENGTH); | |
struct group *g; | |
g = getgrgid(sb.st_gid); | |
if (g == NULL) { | |
printf(ANSI_COLOR_RED"Error group not found\n"ANSI_COLOR_RESET); | |
return -1; | |
} | |
strncat(file_info,g->gr_name,strlen(g->gr_name)); | |
printToScreen(file_info, 0); | |
memset(file_info,0,FILEINFOLENGTH); | |
//file size | |
char str[256]; | |
snprintf(str, 256,"%ld",sb.st_size); | |
strncat(file_info, str, strlen(str)); | |
printToScreen(file_info, 8); | |
memset(file_info,0,FILEINFOLENGTH); | |
//modification dates | |
struct tm *info; | |
info = localtime( &sb.st_mtime); | |
memset(str,0,256); | |
strftime(str,256,"%b %d %H:%M", info); | |
strncat(file_info, str, strlen(str)); | |
printToScreen(file_info, 0); | |
memset(file_info,0,FILEINFOLENGTH); | |
} | |
strncat(file_info, dp->d_name, strlen(dp->d_name)); | |
printToScreen(file_info, 0); | |
memset(file_info,0,FILEINFOLENGTH); | |
printf("\n"); | |
if(toggle == 0) | |
toggle = 1; | |
else | |
toggle = 0; | |
errno = ENOENT; | |
} | |
if(errno != ENOENT) | |
printf(ANSI_COLOR_RED"Error reading the directory [%s]\n"ANSI_COLOR_RESET,strerror(errno)); | |
if(closedir(directory) == -1) | |
printf(ANSI_COLOR_RED"Error closing the directory\n"ANSI_COLOR_RESET); | |
return (EXIT_SUCCESS); | |
} | |
/** | |
* prints the line with padding and toggle color | |
* @param in char to print | |
* @param targetStrLen padding to apply | |
*/ | |
void printToScreen(char* in, int targetStrLen){ | |
//display hidden files | |
const char *padding=""; | |
int padLen = targetStrLen - strlen(in); // Calc Padding length | |
if(padLen < 0) padLen = 0; // Avoid negative length | |
if(toggle == 0) | |
printf(ANSI_COLOR_GREEN"[%*.*s%s]"ANSI_COLOR_RESET, padLen, padLen, padding, in); | |
else | |
printf(ANSI_COLOR_BLUE"[%*.*s%s]"ANSI_COLOR_RESET, padLen, padLen, padding, in); | |
} | |
/** | |
* gets the current working directory using getcwd | |
* @param path array to write to | |
* @param size size of array | |
* @return 0 on success -1 on fail | |
*/ | |
int getCurrentWorkingDirectory(char* path,int size){ | |
if (getcwd(path, size) != NULL) | |
return 0; | |
else | |
return -1; | |
} | |
/** | |
* Initialize an array with "empty" options | |
* @param arr array to initilize | |
* @param size size of the array | |
*/ | |
void initOptions(options *arr, int size){ | |
for(int i=0; i<size; i++) | |
arr[i] = No; | |
} | |
/** | |
* analysis given arguments for type. argv[0] will be ignored! | |
* @param argc count of arguments | |
* @param argv list of arguments | |
* @param arr list of options that where detected | |
* @param size size of arr | |
* @return retuns | |
* 0 on success, | |
* -1 on error and | |
* 1 when a argument is detected that doesn't exist | |
*/ | |
int getOptions(int argc, char** argv, options *arr, int size){ | |
if(size < 1) | |
return -1; | |
int c; | |
while ((c = getopt (argc, argv, "la")) != -1) | |
switch (c) | |
{ | |
case 'a': | |
addToList(arr, size, Allhidden); | |
break; | |
case 'l': | |
addToList(arr, size, Listlong); | |
break; | |
case '?': | |
return 1; | |
default: | |
//return 0; | |
abort(); | |
} | |
return 0; | |
/* | |
int res = 0; | |
char param[MAXARGUMENTS]; | |
int k = 0; | |
//go through argv and enter all symbols to a list | |
for(int i=1; i<argc; i++){ | |
for(int j=0; j < strlen(argv[i]) - 1; j++){ | |
param[k++] = argv[i][j+1]; | |
if(k >= MAXARGUMENTS) | |
return -1; | |
} | |
} | |
//printf("params: %s", param); | |
//check list if argument matches list entry | |
for(int i=0; i<MAXARGUMENTS; i++){ | |
for(int j=0; j<NKEYS; j++){ | |
if(param[i] == lookuptable[j].key){ | |
printf(ANSI_COLOR_GREEN"Try to add %d\n"ANSI_COLOR_RESET, lookuptable[j].val); | |
addToList(arr, size, lookuptable[j].val); | |
} else {//argument detected that isnt in the list | |
res = 1; | |
} | |
} | |
} | |
return res; | |
*/ | |
} | |
/** | |
* appends an option to the list if it isn't part of it yet. | |
* @param arr list to append to | |
* @param size size of list | |
* @param val value to append | |
* @return 0 on success and -1 on error | |
* (if the item is already part of the list 0 is returned) | |
*/ | |
int addToList(options *arr, int size, options val){ | |
int in_list = 0; | |
int res = 0; | |
//printf("Trying to add: %d\n", val); | |
//check if value is on list | |
for(int i=0; i < size; i++){ | |
if(arr[i] == val) | |
in_list = 1; | |
} | |
//return when already in list | |
if(in_list == 1) | |
return res; | |
res = -1; | |
//try to add item to list return will stay -1 when no space | |
for(int i=0; i < size; i++){ | |
if(arr[i] == No){ | |
res = 0; | |
arr[i] = val; | |
break; | |
} | |
} | |
return res; | |
} | |
/** | |
* checks if a given value is part of the list | |
* @param arr list | |
* @param size size of list | |
* @param val value to ceck | |
* @return 1 if item is in the list, 0 if not | |
*/ | |
int listContains(options *arr, int size, options val){ | |
//check if value is on list | |
for(int i=0; i < size; i++){ | |
if(arr[i] == val) | |
return 1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment