]> git.sur5r.net Git - cc65/commitdiff
add "tinyshell" test program for file operations
authorChristian Groessler <chris@groessler.org>
Wed, 24 Jul 2013 13:04:56 +0000 (15:04 +0200)
committerChristian Groessler <chris@groessler.org>
Wed, 24 Jul 2013 13:04:56 +0000 (15:04 +0200)
testcode/lib/tinyshell.c [new file with mode: 0644]

diff --git a/testcode/lib/tinyshell.c b/testcode/lib/tinyshell.c
new file mode 100644 (file)
index 0000000..f4a1812
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Simple ("tiny") shell to test filename and directory functions.
+ * Copyright (c) 2013, Christian Groessler, chris@groessler.org
+ */
+
+#define VERSION_ASC "0.90"
+
+#define KEYB_BUFSZ 80
+#define PROMPT ">>> "
+#ifdef __ATARI__
+#define UPPERCASE      /* define (e.g. for Atari) to convert filenames etc. to upper case */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#ifndef __CC65__
+#include <sys/stat.h>
+#include <sys/param.h>
+#else
+#define MAXPATHLEN 64
+#endif
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#define CMD_NOTHING 0
+#define CMD_INVALID 1
+#define CMD_HELP    2
+#define CMD_QUIT    3
+#define CMD_LS      4
+#define CMD_MKDIR   5
+#define CMD_RMDIR   6
+#define CMD_CHDIR   7
+#define CMD_RM      8
+#define CMD_RENAME  9
+#define CMD_COPY    10
+#define CMD_PWD     11
+
+static unsigned char terminate;
+static unsigned char cmd;
+static unsigned char *cmd_asc, *arg1, *arg2, *arg3;
+static unsigned char keyb_buf[KEYB_BUFSZ];
+static size_t cpbuf_sz = 4096;
+
+struct cmd_table {
+    unsigned char *name;
+    unsigned char code;
+} cmd_table[] = {
+    { "help",  CMD_HELP },
+    { "quit",  CMD_QUIT },
+    { "q",     CMD_QUIT },
+    { "exit",  CMD_QUIT },
+    { "ls",    CMD_LS },
+    { "dir",   CMD_LS },
+    { "md",    CMD_MKDIR },
+    { "mkdir", CMD_MKDIR },
+    { "rd",    CMD_RMDIR },
+    { "rmdir", CMD_RMDIR },
+    { "cd",    CMD_CHDIR },
+    { "chdir", CMD_CHDIR },
+    { "rm",    CMD_RM },
+    { "del",   CMD_RM },
+    { "cp",    CMD_COPY },
+    { "copy",  CMD_COPY },
+    { "mv",    CMD_RENAME },
+    { "ren",   CMD_RENAME },
+    { "pwd",   CMD_PWD },
+    { NULL, 0 }
+};
+
+static void banner(void)
+{
+    puts("\"tiny\" command line shell, v" VERSION_ASC);
+    puts("written by chris@groessler.org");
+    puts("type 'help' for help\n");
+}
+
+static void get_command(void)
+{
+    unsigned char i = 0;
+
+    arg1 = arg2 = arg3 = NULL;
+
+    /* issue prompt */
+    printf(PROMPT);
+
+    /* get input from the user */
+    if (! fgets(keyb_buf, KEYB_BUFSZ, stdin)) {
+        puts("");
+        cmd = CMD_QUIT;
+        return;
+    }
+
+    /* split input into cmd, arg1, arg2, arg3 */
+
+    /* get and parse command */
+    cmd_asc = strtok(keyb_buf, " \t\n");
+    if (! cmd_asc) {
+        cmd = CMD_NOTHING;
+        return;
+    }
+    cmd = CMD_INVALID;
+    while (cmd_table[i].name) {
+        if (! strcmp(cmd_table[i].name, cmd_asc)) {
+            cmd = cmd_table[i].code;
+            break;
+        }
+        i++;
+    }
+
+    /* get arguments */
+    arg1 = strtok(NULL, " \t\n");
+    if (! arg1)
+        return;
+    arg2 = strtok(NULL, " \t\n");
+    if (! arg2)
+        return;
+    arg3 = strtok(NULL, " \t\n");
+}
+
+static void cmd_help(void)
+{
+    puts("quit, exit -  exit shell");
+    puts("ls, dir    -  display current directory");
+    puts("              and drive contents");
+    puts("rm, del    -  delete file");
+    puts("cp, copy   -  copy file");
+    puts("mv, ren    -  rename file");
+    puts("cd, chdir  -  change directory or drive");
+    puts("md, mkdir  -  make directory or drive");
+    puts("rd, rmdir  -  remove directory or drive");
+    puts("sorry, you cannot start programs here");
+}
+
+static void cmd_ls(void)
+{
+    DIR *dir;
+    unsigned char *arg;
+    struct dirent *dirent;
+#ifdef __ATARI__
+    char need_free = 0;
+#endif
+
+    if (arg2) {
+        puts("usage: ls [dir]");
+        return;
+    }
+
+    /* print directory listing */
+    if (arg1) {
+#ifdef UPPERCASE
+        strupr(arg1);
+#endif
+#ifdef __ATARI__
+        /* not sure if this shouldn't be done by the runtime lib */
+        if (*(arg1 + strlen(arg1) - 1) == ':' || *(arg1 + strlen(arg1) - 1) == '>') {
+            arg = malloc(strlen(arg1) + 4);
+            if (! arg) {
+                printf("malloc failed: %s", strerror(errno));
+                return;
+            }
+            need_free = 1;
+            memcpy(arg, arg1, strlen(arg1) + 1);
+            strcat(arg, "*.*");
+        }
+        else
+#endif
+            arg = arg1;
+    }
+    else
+        arg = ".";
+
+    dir = opendir(arg);
+#ifdef __ATARI__
+    if (need_free) free(arg);
+#endif
+    if (! dir) {
+        puts("opendir failed");
+        return;
+    }
+
+    while (dirent = readdir(dir))
+        puts(dirent->d_name);
+
+    closedir(dir);
+}
+
+static void cmd_rm(void)
+{
+    if (!arg1 || arg2) {
+        puts("usage: rm <file>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+#endif
+
+    if (unlink(arg1))
+        printf("remove failed: %s\n", strerror(errno));
+}
+
+static void cmd_mkdir(void)
+{
+    if (!arg1 || arg2) {
+        puts("usage: mkdir <dir>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+#endif
+
+    if (mkdir(arg1, 0777))
+        printf("mkdir failed: %s\n", strerror(errno));
+}
+
+static void cmd_rmdir(void)
+{
+    if (!arg1 || arg2) {
+        puts("usage: rmdir <dir>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+#endif
+
+    if (rmdir(arg1))
+        printf("rmdir failed: %s\n", strerror(errno));
+}
+
+static void cmd_chdir(void)
+{
+    if (!arg1 || arg2) {
+        puts("usage: cddir <dir>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+#endif
+
+    if (chdir(arg1))
+        printf("chdir failed: %s\n", strerror(errno));
+}
+
+static void cmd_pwd(void)
+{
+    char *buf;
+
+    if (arg1) {
+        puts("usage: pwd");
+        return;
+    }
+
+    buf = malloc(MAXPATHLEN);
+    if (! buf) {
+        printf("malloc %u bytes failed: %s\n", MAXPATHLEN, strerror(errno));
+        return;
+    }
+    if (!getcwd(buf, MAXPATHLEN)) {
+        printf("getcwd failed: %s\n", strerror(errno));
+        free(buf);
+        return;
+    }
+
+    puts(buf);
+    free(buf);
+}
+
+static void cmd_rename(void)
+{
+    if (!arg2 || arg3) {
+        puts("usage: mv <oldname> <newname>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+    strupr(arg2);
+#endif
+
+    if (rename(arg1, arg2))
+        printf("rename failed: %s\n", strerror(errno));
+}
+
+static void cmd_copy(void)
+{
+    int srcfd = -1, dstfd = -1;
+    unsigned char *buf;
+    int readsz, writesz;
+
+    if (!arg2 || arg3) {
+        puts("usage: cp <src> <dest>");
+        return;
+    }
+
+#ifdef UPPERCASE
+    strupr(arg1);
+    strupr(arg2);
+#endif
+
+    buf = malloc(cpbuf_sz);
+    if (! buf) {
+        printf("malloc %u bytes failed: %s\n", cpbuf_sz, strerror(errno));
+        return;
+    }
+
+    while (1) {
+        if (srcfd == -1) {
+            srcfd = open(arg1, O_RDONLY);
+            if (srcfd < 0) {
+                printf("open(%s) failed: %s\n", arg1, strerror(errno));
+                break;
+            }
+        }
+
+        readsz = read(srcfd, buf, cpbuf_sz);
+        if (readsz < 0) {
+            printf("read error: %s\n", strerror(errno));
+            break;
+        }
+        if (! readsz)
+            break;
+
+        if (dstfd == -1) {
+            dstfd = open(arg2, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+            if (dstfd < 0) {
+                printf("open(%s) failed: %s\n", arg2, strerror(errno));
+                break;
+            }
+        }
+
+        writesz = write(dstfd, buf, readsz);
+        if (writesz < 0 || writesz != readsz) {
+            printf("write error: %s\n", strerror(errno));
+            break;
+        }
+        if (readsz != cpbuf_sz)
+            break;
+    }
+
+    free(buf);
+    if (srcfd >= 0) close(srcfd);
+    if (dstfd >= 0) close(dstfd);
+}
+
+static void run_command(void)
+{
+    switch (cmd) {
+        default: puts("internal error"); return;
+        case CMD_NOTHING: return;
+        case CMD_INVALID: puts("invalid command"); return;
+        case CMD_HELP: cmd_help(); return;
+        case CMD_QUIT: terminate = 1; return;
+        case CMD_LS: cmd_ls(); return;
+        case CMD_RM: cmd_rm(); return;
+        case CMD_CHDIR: cmd_chdir(); return;
+        case CMD_MKDIR: cmd_mkdir(); return;
+        case CMD_RMDIR: cmd_rmdir(); return;
+        case CMD_PWD: cmd_pwd(); return;
+        case CMD_RENAME: cmd_rename(); return;
+        case CMD_COPY: cmd_copy(); return;
+    }
+}
+
+int main(void)
+{
+    banner();
+
+    while (! terminate) {
+        get_command();
+        run_command();
+    }
+    return 0;
+}
+
+/* Local Variables: */
+/* c-file-style: "cpg" */
+/* c-basic-offset: 4 */
+/* End: */