Implement internal commands, clean up a bit

This commit is contained in:
Artur Tamborski 2018-12-17 01:46:00 +01:00
parent 360cf24ae2
commit df27b4f66c
3 changed files with 148 additions and 63 deletions

View File

@ -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 */

View File

@ -1,68 +1,172 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include "icmd.h" #include "icmd.h"
#include "common.h"
#define ICMDS_SIZE \ #define ICMDS_SIZE \
(sizeof(g_icmds) / sizeof(g_icmds[0])) (sizeof(g_icmds) / sizeof(g_icmds[0])) \
#define ICMD(name) \
{ \
.cmd = TOSTR(name), \
.len = sizeof(TOSTR(name))-1, \
.func = CONCAT(icmd_, name), \
}
struct icmd g_icmds[] = #define ICMD(name) \
{ \
.cmd = #name, \
.len = sizeof(#name) - 1, \
.func = icmd_##name, \
} \
struct icmd
{ {
ICMD(exit), char *cmd;
ICMD(cd), int len;
ICMD(ls), 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++) va_start(args, format);
{ if (status != 0)
printf("cmp: '%s' : '%s' with len %d \n", g_icmds[i].cmd, line, g_icmds[i].len); printf("%s: Error: ", func);
if (strncmp(g_icmds[i].cmd, line, g_icmds[i].len) == 0) vprintf(format, args);
return g_icmds[i].func(line); if (status != 0)
} putchar('!');
putchar('\n');
/* todo: find better way to signal this? */ if (status < 0)
/* maybe return function pointer? */ perror("Reason");
return INT_MAX; va_end(args);
} }
int int
icmd_exit(char *line) call_icmd(int argc, char **argv)
{ {
printf("exiting with reason: %s", line); size_t i;
exit(0);
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 int
icmd_cd(char *line) icmd_help(int argc, char **argv)
{ {
printf("I'm a cd! line: %s\n", line); size_t i;
return 0;
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 int
icmd_ls(char *line) icmd_exit(int argc, char **argv)
{ {
printf("I'm a ls! line: %s\n", line); puts("good bye!");
return 1; 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;
} }

View File

@ -2,22 +2,16 @@
#define ICMD_H #define ICMD_H
struct icmd /* API */
{ int call_icmd(int argc, char **argv);
char *cmd;
int len;
int (*func)(char *);
};
/* interface */ /* internal commands */
int call_icmds(char *line); int icmd_help(int argc, char **argv);
int icmd_exit(int argc, char **argv);
int icmd_cls(int argc, char **argv);
/* internal commands as functions */ int icmd_cd(int argc, char **argv);
int icmd_exit(char *line); int icmd_ls(int argc, char **argv);
int icmd_cd(char *line);
int icmd_ls(char *line);
#endif /* ICMD_H */ #endif /* ICMD_H */