#include #include #include #include #include #include #ifdef USE_READLINE #include #include #endif // USE_READLINE typedef int (*repl_command)(int, const struct param*, int, char**); static int repl_read(int fd, const struct param *param, int argc, char **args) { int err = 0; uint8_t buf[MAX_PACKET_SIZE]; uint8_t bank; uint16_t address; uint16_t length; const char *pathname = NULL; if (argc != 3 && argc != 4) goto syntax_error; errno = 0; bank = strtoul(args[0], NULL, 16); err |= errno; errno = 0; address = strtoul(args[1], NULL, 16); err |= errno; errno = 0; length = strtoul(args[2], NULL, 16); err |= errno; if (argc == 4) pathname = args[3]; if (err) goto syntax_error; if ((err = z_read(fd, bank, address, length, buf))) { print_error(err); return err; } hexdump(address, length, buf); if (pathname) { FILE *file; if (!(file = fopen(pathname, "w"))) { perror("File could not be opened"); return -1; } fwrite(buf, sizeof(uint8_t), length, file); fclose(file); } return err; syntax_error: fputs("Usage: read
[pathname]\n", stderr); return 1; } /* static int parse_args(const char *fname, const char *types, int argc, char **args, ...) { } */ static int repl_write(int fd, const struct param *param, int argc, char **args) { int err; char line[512]; uint8_t buf[MAX_PACKET_SIZE]; char *p; uint8_t bank; uint16_t address; uint16_t length = 0; do { // TODO: Handle fgets error fgets(line, LEN(line), stdin); if (line && !strcmp("\n", line)) break; p = strtok(line, " \n"); while (p && length < 10) { errno = 0; buf[length++] = strtoul(p, NULL, 16); p = strtok(NULL, " \n"); } if (p) { fputs("WRITE: Input can't be longer than 256 bytes\n", stderr); return -1; } } while (1); if ((err = z_write(fd, bank, address, length, buf))) { print_error(err); return err; } return 0; } static int repl_echo(int fd, const struct param *param, int argc, char **args) { int err; char line[512]; char buf[MAX_PACKET_SIZE]; memset(line, 0, sizeof(line)); memset(buf, 0, sizeof(buf)); size_t length = 0; do { // TODO: Handle fgets error fgets(line, LEN(line), stdin); if (line && !strcmp("\n", line)) break; size_t len = strlen(line); if (line[len - 1] == '\n') line[--len] = '\0'; if (length + len >= MAX_PACKET_SIZE) { fputs("ECHO: Input can't be longer than 256 bytes\n", stderr); return -1; } strcat(buf, line); length += len; } while (1); if ((err = z_echo(fd, length, (uint8_t *)buf))) { print_error(err); return err; } fwrite(buf, sizeof(uint8_t), length, stdout); putchar('\n'); fflush(stdout); return 0; } static int repl_io_read(int fd, const struct param *param, int argc, char **args) { return 0; } static int repl_io_write(int fd, const struct param *param, int argc, char **args) { return 0; } /* static volatile sig_atomic_t quit = 0; void interrupt_handler(int signal) { puts("Bye!"); quit = 1; // fclose(stdin); } */ // TODO: Handle signals (CTRL-C) // TODO: Print errors when in repl and crash if from terminal void repl(int fd, struct param *param) { struct command { const char *name; repl_command fptr; int quit; }; const struct command cmd_table[] = { {"read", repl_read, 0}, {"write", repl_write, 0}, {"echo", repl_echo, 0}, {"io_read", repl_io_read, 0}, {"io_write", repl_io_write, 0}, {"quit", NULL, 1} }; int quit = 0; #ifdef USE_READLINE using_history(); #endif while (!quit) { #ifdef USE_READLINE char *line = readline("* "); if (!line) break; add_history(line); #else size_t len = 0; char line[512]; fputs("* ", stdout); if (!fgets(line, sizeof(line), stdin)) break; len = strlen(line); if (line[len - 1] == '\n') line[len - 1] = '\0'; #endif int argc = 1; char *args[MAX_ARGS] = { NULL }; // Parse command args[0] = strtok(line, " "); if (!args[0]) goto skip; while(argc < MAX_ARGS && (args[argc] = strtok(NULL, " "))) ++argc; // Match action int cmdi; for (cmdi = 0; cmdi < LEN(cmd_table); ++cmdi) { if (!strcmp(args[0], cmd_table[cmdi].name)) break; } // Call action if (cmdi == LEN(cmd_table)) { fprintf(stdout, "Unknown command %s\n", args[0]); } else { repl_command fptr = cmd_table[cmdi].fptr; if (fptr) fptr(fd, param, argc - 1, &args[1]); quit = cmd_table[cmdi].quit; } skip: #ifdef USE_READLINE free(line); #endif } }