diff --git a/src/common.h b/src/common.h deleted file mode 100644 index 8f8af8c..0000000 --- a/src/common.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - - -#define CONCAT(x,y) _CONCAT(x,y) -#define _CONCAT(x,y) (x##y) - - -#define TOSTR(x) _TOSTR(x) -#define _TOSTR(x) (#x) - - -#endif /* COMMON_H */ diff --git a/src/icmd.c b/src/icmd.c index 9d028dc..ef9a603 100644 --- a/src/icmd.c +++ b/src/icmd.c @@ -1,68 +1,172 @@ #include #include +#include +#include #include #include +#include +#include +#include #include "icmd.h" -#include "common.h" -#define ICMDS_SIZE \ - (sizeof(g_icmds) / sizeof(g_icmds[0])) - -#define ICMD(name) \ - { \ - .cmd = TOSTR(name), \ - .len = sizeof(TOSTR(name))-1, \ - .func = CONCAT(icmd_, name), \ - } +#define ICMDS_SIZE \ + (sizeof(g_icmds) / sizeof(g_icmds[0])) \ -struct icmd g_icmds[] = +#define ICMD(name) \ + { \ + .cmd = #name, \ + .len = sizeof(#name) - 1, \ + .func = icmd_##name, \ + } \ + + +struct icmd { - ICMD(exit), - ICMD(cd), - ICMD(ls), + char *cmd; + int len; + int (*func)(int, char **); + +} g_icmds[] = +{ + ICMD(help), + ICMD(exit), + ICMD(cls), + ICMD(cd), + ICMD(ls), }; -int -call_icmds(char *line) + +#define icmd_die(status, ...) \ + { \ + _icmd_die(status, argv[0], __VA_ARGS__); \ + return status; \ + } \ + + +static void +_icmd_die(int status, char *func, char *format, ...) { - size_t i; + va_list args; - for (i = 0; i < ICMDS_SIZE; i++) - { - printf("cmp: '%s' : '%s' with len %d \n", g_icmds[i].cmd, line, g_icmds[i].len); - if (strncmp(g_icmds[i].cmd, line, g_icmds[i].len) == 0) - return g_icmds[i].func(line); - } - - /* todo: find better way to signal this? */ - /* maybe return function pointer? */ - return INT_MAX; + va_start(args, format); + if (status != 0) + printf("%s: Error: ", func); + vprintf(format, args); + if (status != 0) + putchar('!'); + putchar('\n'); + if (status < 0) + perror("Reason"); + va_end(args); } int -icmd_exit(char *line) +call_icmd(int argc, char **argv) { - printf("exiting with reason: %s", line); - exit(0); + size_t i; + + for (i = 0; i < ICMDS_SIZE; i++) + if (strncmp(g_icmds[i].cmd, argv[0], g_icmds[i].len) == 0) + return g_icmds[i].func(argc, argv); + + return INT_MAX; } int -icmd_cd(char *line) +icmd_help(int argc, char **argv) { - printf("I'm a cd! line: %s\n", line); - return 0; + size_t i; + + puts( + "\n psh - poor man's shell" + "\n " + "\n internal commands: " + ); + + for (i = 0; i < ICMDS_SIZE; i++) + printf(" - %s\n", g_icmds[i].cmd); + + putchar('\n'); + + return 0; } int -icmd_ls(char *line) +icmd_exit(int argc, char **argv) { - printf("I'm a ls! line: %s\n", line); - return 1; + puts("good bye!"); + exit(0); + + return 0; +} + + +int +icmd_cls(int argc, char **argv) +{ + int i = 24; + + while (i--) + putchar('\n'); + + return 0; +} + + +int +icmd_cd(int argc, char **argv) +{ + char def_path[] = "."; + char *path = def_path; + + if (argc > 2) + icmd_die(1, "too many arguments given"); + + if (argc == 2) + path = argv[1]; + + if (chdir(path)) + icmd_die(-1, "could not change directory"); + + return 0; +} + + +int +icmd_ls(int argc, char **argv) +{ + char def_path[] = "."; + char *path = def_path; + struct dirent *d; + DIR *dir; + int i = 1; + + if (argc > 1) + path = argv[1]; + + do + { + if ((dir = opendir(path)) == NULL) + icmd_die(-1, "could not open directory '%s'", path); + + puts(path); + while ((d = readdir(dir)) != NULL) + /* don't print current directory '.' and parent directory '..' */ + if (!(d->d_name[0] == '.' && (d->d_name[1] == '\0' || d->d_name[1] == '.'))) + printf(" %s\n", d->d_name); + + closedir(dir); + putchar('\n'); + path = argv[++i]; + + } while (i < argc); + + return 0; } diff --git a/src/icmd.h b/src/icmd.h index dc444a8..1cfe9d1 100644 --- a/src/icmd.h +++ b/src/icmd.h @@ -2,22 +2,16 @@ #define ICMD_H -struct icmd -{ - char *cmd; - int len; - int (*func)(char *); -}; +/* API */ +int call_icmd(int argc, char **argv); -/* interface */ -int call_icmds(char *line); - - -/* internal commands as functions */ -int icmd_exit(char *line); -int icmd_cd(char *line); -int icmd_ls(char *line); +/* internal commands */ +int icmd_help(int argc, char **argv); +int icmd_exit(int argc, char **argv); +int icmd_cls(int argc, char **argv); +int icmd_cd(int argc, char **argv); +int icmd_ls(int argc, char **argv); #endif /* ICMD_H */