Skip to content

Instantly share code, notes, and snippets.

@Cranc
Last active December 18, 2017 20:15
Show Gist options
  • Save Cranc/2de61c7d0b405795a71dfafb93417b74 to your computer and use it in GitHub Desktop.
Save Cranc/2de61c7d0b405795a71dfafb93417b74 to your computer and use it in GitHub Desktop.
/*
* 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