From d7e7c6977a0376747269ad905cff1af18f85831d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Tue, 14 Mar 2023 17:35:08 +0100 Subject: work --- Makefile | 17 +++- analyze-gz.c | 280 ------------------------------------------------------- analyze_gz.c | 88 +++++++++++++++++ format.c | 188 +++++++++++++++++++++++++++++++++++++ format.h | 13 +++ gzip.h | 77 +++++++++++++++ hexdump_pretty.c | 125 +++++++++++++++++++++++++ hexdump_pretty.h | 37 ++++++++ ui.c | 116 +++++++++++++++++------ 9 files changed, 630 insertions(+), 311 deletions(-) delete mode 100644 analyze-gz.c create mode 100644 analyze_gz.c create mode 100644 format.c create mode 100644 format.h create mode 100644 gzip.h create mode 100644 hexdump_pretty.c create mode 100644 hexdump_pretty.h diff --git a/Makefile b/Makefile index 1221184..08d61cf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,17 @@ -CFLAGS = -Wall -std=c11 -ggdb +CFLAGS = -Wall -std=c11 -ggdb -D_POSIX_C_SOURCE=200809L LDLIBS = -lncurses -analyze-gc: analyze-gz.c +.PHONY: all +all: analyze_gz ui + +analyze_gz: analyze_gz.o hexdump_pretty.o + $(CC) $^ -o $@ $(LDLIBS) + +ui: ui.o format.o + $(CC) $^ -o $@ $(LDLIBS) + +analyze_gz.o: analyze_gz.c hexdump_pretty.h gzip.h +hexdump_pretty.o: hexdump_pretty.c hexdump_pretty.h +format.o: format.c format.h gzip.h +ui.o: ui.c format.h -ui: ui.c diff --git a/analyze-gz.c b/analyze-gz.c deleted file mode 100644 index a0c6d40..0000000 --- a/analyze-gz.c +++ /dev/null @@ -1,280 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include - -#define ID1 31 -#define ID2 139 - -enum compression_method { - DEFLATE = 8, -}; - -enum flag { - FTEXT = 1 << 0, - FHCRC = 1 << 1, - FEXTRA = 1 << 2, - FNAME = 1 << 3, - FCOMMENT = 1 << 4, -}; - -enum operating_system { - FAT = 0, - AMIGA, - VMS, - UNIX, - CMS, - ATARI_TOS, - HPFS, - MACINTOSH, - Z_SYSTEM, - CP_M, - TOPS20, - NTFS, - QDOS, - ACORN_RISCOS, -}; - -const char *os_str(enum operating_system os) { - switch (os) { - case FAT: return "FAT filesystem (MS-DOS, OS/2, NT/Win32)"; - case AMIGA: return "Amiga"; - case VMS: return "VMS (or OpenVMS)"; - case UNIX: return "Unix"; - case CMS: return "VM/CMS"; - case ATARI_TOS: return "Atari TOS"; - case HPFS: return "HPFS filesystem (OS/2, NT)"; - case MACINTOSH: return "Macintosh"; - case Z_SYSTEM: return "Z-System"; - case CP_M: return "CP/M"; - case TOPS20: return "TOPS-20"; - case NTFS: return "NTFS filesystem (NT)"; - case QDOS: return "QDOS"; - case ACORN_RISCOS: return "Acorn RISCOS"; - default: return "unknown"; - } -} - -struct member { - uint8_t id1, id2, cm, flg; - uint32_t mtime; - uint8_t xfl, os; -} __attribute__((packed)); - - -enum color { - BLACK = 0, - RED, - GREEN, - YELLOW, - BLUE, - PURPLE, - CYAN, - WHITE, -}; - - -struct segment { - enum color c; - size_t len; - uint8_t *data; -}; - -enum color next_color(void) { - static uint8_t cc = 0; - cc += 1; - cc %= 6; - return cc + 1; -} - -void color_put(enum color c) { - printf("\x1b[0;3%im", c); -} - -void color_reset(void) { - printf("\x1b[m"); -} - -#define LINELEN 0x8 -struct segment line_segments[LINELEN]; -size_t file_idx = 0; -size_t line_idx = 0; -size_t current_segment = 0; - -void cleanup_line(void) { - for (int i = 0; i < current_segment; i++) { - free(line_segments[i].data); - } -} - -void put_byte(uint8_t byte) { - static bool flip = 0; - printf("%02x", byte); - flip = !flip; - if (! flip) { - printf(" "); - } -} - -void flush_line() { - printf("%06lx: ", file_idx); - file_idx += LINELEN; - for (int i = 0; i < current_segment; i++) { - color_put(line_segments[i].c); - for (int b = 0; b < line_segments[i].len; b++) { - put_byte(line_segments[i].data[b]); - } - color_reset(); - } - for (int i = 0; i < current_segment; i++) { - color_put(line_segments[i].c); - for (int b = 0; b < line_segments[i].len; b++) { - uint8_t ch = line_segments[i].data[b]; - if (isprint(ch)) { - printf("%c", ch); - } else { - printf("."); - } - } - color_reset(); - } - printf("\n"); -} - -void add_segment(struct segment segment) { - line_segments[current_segment++] = segment; - line_idx += segment.len; - if (line_idx == LINELEN) { - flush_line(); - cleanup_line(); - current_segment = 0; - line_idx = 0; - } -} - -/* - * Buf MUST be a malloc:ed buffer, which is invalidated on this call. - */ -void write_chunk(uint8_t *buf, size_t len) { - if (line_idx + len >= LINELEN) { - enum color c = next_color(); - size_t len1 = LINELEN - line_idx, - len2 = len - len1; - uint8_t *buf1 = malloc(len1), - *buf2 = malloc(len2); - memcpy(buf1, buf, len1); - memcpy(buf2, buf + len1, len2); - free(buf); - struct segment - seg1 = { - .c = c, - .len = len1, - .data = buf1, - }, - seg2 = { - .c = c, - .len = len2, - .data = buf2, - }; - add_segment(seg1); - add_segment(seg2); - } else { - struct segment seg = { - .c = next_color(), - .len = len, - .data = buf, - }; - add_segment(seg); - } -} - -void write_chunk_s(uint8_t *buf, size_t len) { - assert (len >= 0); - uint8_t *true_buf = malloc(len); - memcpy(true_buf, buf, len); - write_chunk(true_buf, len); -} - -int main(int argc, char *argv[]) { - if (argc == 1) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; - } - - FILE *f = fopen(argv[1], "rb"); - size_t len; - - struct member header; - uint8_t *extra_fields = NULL; - uint16_t crc16 = 0; - char *filename = NULL; - char *file_comment = NULL; - - len = fread(&header, sizeof(header), 1, f); - - if (len != 1) { - fprintf(stderr, "Unexpected end of header\n"); - return 1; - } - - write_chunk_s((uint8_t[2]) {header.id1, header.id2}, 2); - write_chunk_s(&header.cm, 1); - write_chunk_s(&header.flg, 1); - { - size_t s = sizeof(header.mtime); - uint8_t *buf = malloc(s); - memcpy(buf, &header.mtime, s); - write_chunk(buf, s); - } - write_chunk_s(&header.xfl, 1); - write_chunk_s(&header.os, 1); - - if (header.flg & FEXTRA) { - uint16_t xlen; - len = fread(&xlen, sizeof(xlen), 1, f); - { - uint8_t *buf = malloc(len); - memcpy(buf, &xlen, len); - write_chunk(buf, len); - } - extra_fields = malloc(xlen); - len = fread(extra_fields, 1, xlen, f); - write_chunk(extra_fields, xlen); - } - - if (header.flg & FNAME) { - size_t n; - len = getdelim(&filename, &n, '\0', f); - write_chunk((uint8_t*) filename, n); - } - - if (header.flg & FCOMMENT) { - size_t n; - len = getdelim(&file_comment, &n, '\0', f); - write_chunk((uint8_t*) file_comment, n); - } - - if (header.flg & FHCRC) { - len = fread(&crc16, sizeof(crc16), 1, f); - { - uint8_t *buf = malloc(len); - memcpy(buf, &crc16, len); - write_chunk(buf, len); - } - } - -// cleanup: - if (extra_fields) free(extra_fields); - if (filename) free(filename); - if (file_comment) free(file_comment); - flush_line(); - cleanup_line(); - - printf("\n"); - - -} diff --git a/analyze_gz.c b/analyze_gz.c new file mode 100644 index 0000000..1ea0d78 --- /dev/null +++ b/analyze_gz.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +#include "hexdump_pretty.h" + +#include "gzip.h" + +int main(int argc, char *argv[]) { + if (argc == 1) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + FILE *f = fopen(argv[1], "rb"); + size_t len; + + struct member header; + uint8_t *extra_fields = NULL; + uint16_t crc16 = 0; + char *filename = NULL; + char *file_comment = NULL; + + len = fread(&header, sizeof(header), 1, f); + + if (len != 1) { + fprintf(stderr, "Unexpected end of header\n"); + return 1; + } + + write_chunk_s((uint8_t[2]) {header.id1, header.id2}, 2); + write_chunk_s(&header.cm, 1); + write_chunk_s(&header.flg, 1); + { + size_t s = sizeof(header.mtime); + uint8_t *buf = malloc(s); + memcpy(buf, &header.mtime, s); + write_chunk(buf, s); + } + write_chunk_s(&header.xfl, 1); + write_chunk_s(&header.os, 1); + + if (header.flg & FEXTRA) { + uint16_t xlen; + len = fread(&xlen, sizeof(xlen), 1, f); + { + uint8_t *buf = malloc(len); + memcpy(buf, &xlen, len); + write_chunk(buf, len); + } + extra_fields = malloc(xlen); + len = fread(extra_fields, 1, xlen, f); + write_chunk(extra_fields, xlen); + } + + if (header.flg & FNAME) { + size_t n; + len = getdelim(&filename, &n, '\0', f); + write_chunk((uint8_t*) filename, n); + } + + if (header.flg & FCOMMENT) { + size_t n; + len = getdelim(&file_comment, &n, '\0', f); + write_chunk((uint8_t*) file_comment, n); + } + + if (header.flg & FHCRC) { + len = fread(&crc16, sizeof(crc16), 1, f); + { + uint8_t *buf = malloc(len); + memcpy(buf, &crc16, len); + write_chunk(buf, len); + } + } + +// cleanup: + if (extra_fields) free(extra_fields); + if (filename) free(filename); + if (file_comment) free(file_comment); + flush_line(); + cleanup_line(); + + printf("\n"); + + +} diff --git a/format.c b/format.c new file mode 100644 index 0000000..cbd7265 --- /dev/null +++ b/format.c @@ -0,0 +1,188 @@ +#include "format.h" +#include "gzip.h" + +#include +#include +#include +#include + +struct segment empty_segment = { + .start = -1, + .end = -1, + .description = "No segment selected", +}; + +struct segment get_segment(void *mem, size_t len, ssize_t addr) { + + if (addr < 0 || addr >= len) { + return empty_segment; + } + + + static char *buf = NULL; + if (buf != NULL) { + free(buf); + buf = NULL; + } + struct member *header = (struct member*) mem; + + if (addr == 0) { + return (struct segment) { + .start = 0, + .end = 1, + .description = "ID1 = 31" + }; + } + if (addr == 1) { + return (struct segment) { + .start = 1, + .end = 2, + .description = "ID2 = 139", + }; + } + if (addr == 2) { + return (struct segment) { + .start = 2, + .end = 3, + .description = "CM (Compression Method)\n" + "CM = 8 is defalte", + }; + } + if (addr == 3) { + buf = malloc(1000); + buf[0] = '\0'; + for (int i = 0; i < 5; i++) { + if (header->flg & (1 << i)) { + strcat(buf, "- "); + strcat(buf, flag_str(1<= 4 && addr < 8) { + buf = malloc(1000); + sprintf(buf, "Mtime=%i", header->mtime); + return (struct segment) { + .start = 4, + .end = 8, + .description = buf, + }; + } + if (addr == 8) { + return (struct segment) { + .start = 8, + .end = 9, + .description = "XFL", + }; + } + if (addr == 9) { + buf = malloc(1000); + sprintf(buf, "OS: %s\n", os_str(header->os)); + return (struct segment) { + .start = 9, + .end = 10, + .description = buf, + }; + } + + void *ptr = ((struct member*) mem) + 1; + + if (header->flg & FEXTRA) { + uint16_t xlen = *((uint16_t*) ptr); + if (mem + addr == ptr || mem + addr == ptr + 1) { + return (struct segment) { + .start = ptr - mem, + .end = ptr - mem + 1, + .description = "XLEN", + }; + } + ptr = ((uint16_t*) ptr) + 1; + // if (mem + addr >= ptr && mem + addr < xlen) { + if (ptr - mem + addr < 2) { + return (struct segment) { + .start = ptr - mem, + .end = ptr - mem + xlen, + .description = "XLEN bytes of extra data", + }; + } + ptr = ((uint8_t*) ptr) + 1 + xlen; + } + + if (header->flg & FNAME) { + void *c = memchr(ptr, '\0', (ptr - mem) + len); + size_t start = ptr - mem; + size_t end = c - mem; + ptr = ((uint8_t*) c) + 1; + if (addr < c - mem + 1) { + return (struct segment) { + .start = start, + .end = end + 1, + .description = "Original filename", + }; + } + } + + if (header->flg & FCOMMENT) { + void *c = memchr(ptr, '\0', (ptr - mem) + len); + ptr = ((uint8_t*) c) + 1; + if (addr < c - mem + 1) { + size_t start = ptr - mem; + size_t end = c - mem; + return (struct segment) { + .start = start, + .end = end + 1, + .description = "File comment", + }; + } + } + + if (header->flg & FHCRC) { + if (addr < ptr - mem + 2) { + buf = malloc(1000); + fprintf(buf, "CRC16=" PRIu16, *((uint16_t*) ptr)); + return (struct segment) { + .start = ptr - mem, + .end = ptr - mem + 2, + .description = buf, + }; + } + ptr = (uint16_t*) ptr + 1; + } + + if (len - addr < 4) { + buf = malloc(1000); + fprintf(buf, "ISIZE" PRIu32, *(((uint32_t*) ((uint8_t*) (mem + len))) - 1)); + return (struct segment) { + .start = len - 4, + .end = len, + .description = buf, + }; + } + + if (len - addr - 4 < 4) { + buf = malloc(1000); + fprintf(buf, "CRC32" PRIu32, *(((uint32_t*) ((uint8_t*) (mem + len))) - 2)); + return (struct segment) { + .start = len - 8, + .end = len - 4, + .description = buf, + }; + } + + if (ptr - mem <= addr && addr < ptr - mem + len - 8) { + return (struct segment) { + .start = ptr - mem, + .end = len - 8, + .description = "ZLIB compressed payload", + }; + } + + + return empty_segment; + +} diff --git a/format.h b/format.h new file mode 100644 index 0000000..b09cb2f --- /dev/null +++ b/format.h @@ -0,0 +1,13 @@ +#ifndef FILE_FORMAT_H +#define FILE_FORMAT_H + +#include + +struct segment { + size_t start, end; + const char *description; +}; + +struct segment get_segment(void *mem, size_t len, ssize_t addr); + +#endif /* FILE_FORMAT_H */ diff --git a/gzip.h b/gzip.h new file mode 100644 index 0000000..e5d5947 --- /dev/null +++ b/gzip.h @@ -0,0 +1,77 @@ +#ifndef GZIP_H +#define GZIP_H + +#include + +/* RFC 1952 */ + +#define ID1 31 +#define ID2 139 + +enum compression_method { + DEFLATE = 8, +}; + +enum flag { + FTEXT = 1 << 0, + FHCRC = 1 << 1, + FEXTRA = 1 << 2, + FNAME = 1 << 3, + FCOMMENT = 1 << 4, +}; + +const char *flag_str (enum flag f) { + switch (f) { + case FTEXT: return "Content is probably text"; + case FHCRC: return "CRC16 is present"; + case FEXTRA: return "Extra field is populated"; + case FNAME: return "A file name is present"; + case FCOMMENT: return "A comment is present"; + default: return "unknown flag"; + } +} + +enum operating_system { + FAT = 0, + AMIGA, + VMS, + UNIX, + CMS, + ATARI_TOS, + HPFS, + MACINTOSH, + Z_SYSTEM, + CP_M, + TOPS20, + NTFS, + QDOS, + ACORN_RISCOS, +}; + +const char *os_str(enum operating_system os) { + switch (os) { + case FAT: return "FAT filesystem (MS-DOS, OS/2, NT/Win32)"; + case AMIGA: return "Amiga"; + case VMS: return "VMS (or OpenVMS)"; + case UNIX: return "Unix"; + case CMS: return "VM/CMS"; + case ATARI_TOS: return "Atari TOS"; + case HPFS: return "HPFS filesystem (OS/2, NT)"; + case MACINTOSH: return "Macintosh"; + case Z_SYSTEM: return "Z-System"; + case CP_M: return "CP/M"; + case TOPS20: return "TOPS-20"; + case NTFS: return "NTFS filesystem (NT)"; + case QDOS: return "QDOS"; + case ACORN_RISCOS: return "Acorn RISCOS"; + default: return "unknown"; + } +} + +struct member { + uint8_t id1, id2, cm, flg; + uint32_t mtime; + uint8_t xfl, os; +} __attribute__((packed)); + +#endif /* GZIP_H */ diff --git a/hexdump_pretty.c b/hexdump_pretty.c new file mode 100644 index 0000000..d082c0b --- /dev/null +++ b/hexdump_pretty.c @@ -0,0 +1,125 @@ +#include "hexdump_pretty.h" + +#include +#include +#include +#include +#include +#include + +#define LINELEN 0x8 + +static struct segment line_segments[LINELEN]; +static size_t file_idx = 0; +static size_t line_idx = 0; +static size_t current_segment = 0; + + +enum color next_color(void) { + static uint8_t cc = 0; + cc += 1; + cc %= 6; + return cc + 1; +} + +void color_put(enum color c) { + printf("\x1b[0;3%im", c); +} + +void color_reset(void) { + printf("\x1b[m"); +} + +void cleanup_line(void) { + for (int i = 0; i < current_segment; i++) { + free(line_segments[i].data); + } +} + +void put_byte(uint8_t byte) { + static bool flip = 0; + printf("%02x", byte); + flip = !flip; + if (! flip) { + printf(" "); + } +} + +void flush_line() { + printf("%06lx: ", file_idx); + file_idx += LINELEN; + for (int i = 0; i < current_segment; i++) { + color_put(line_segments[i].c); + for (int b = 0; b < line_segments[i].len; b++) { + put_byte(line_segments[i].data[b]); + } + color_reset(); + } + for (int i = 0; i < current_segment; i++) { + color_put(line_segments[i].c); + for (int b = 0; b < line_segments[i].len; b++) { + uint8_t ch = line_segments[i].data[b]; + if (isprint(ch)) { + printf("%c", ch); + } else { + printf("."); + } + } + color_reset(); + } + printf("\n"); +} + +void add_segment(struct segment segment) { + line_segments[current_segment++] = segment; + line_idx += segment.len; + if (line_idx == LINELEN) { + flush_line(); + cleanup_line(); + current_segment = 0; + line_idx = 0; + } +} + +/* + * Buf MUST be a malloc:ed buffer, which is invalidated on this call. + */ +void write_chunk(uint8_t *buf, size_t len) { + if (line_idx + len >= LINELEN) { + enum color c = next_color(); + size_t len1 = LINELEN - line_idx, + len2 = len - len1; + uint8_t *buf1 = malloc(len1), + *buf2 = malloc(len2); + memcpy(buf1, buf, len1); + memcpy(buf2, buf + len1, len2); + free(buf); + struct segment + seg1 = { + .c = c, + .len = len1, + .data = buf1, + }, + seg2 = { + .c = c, + .len = len2, + .data = buf2, + }; + add_segment(seg1); + add_segment(seg2); + } else { + struct segment seg = { + .c = next_color(), + .len = len, + .data = buf, + }; + add_segment(seg); + } +} + +void write_chunk_s(uint8_t *buf, size_t len) { + assert (len >= 0); + uint8_t *true_buf = malloc(len); + memcpy(true_buf, buf, len); + write_chunk(true_buf, len); +} diff --git a/hexdump_pretty.h b/hexdump_pretty.h new file mode 100644 index 0000000..c804f37 --- /dev/null +++ b/hexdump_pretty.h @@ -0,0 +1,37 @@ +#ifndef HEXDUMP_PRETTY_H +#define HEXDUMP_PRETTY_H + +#include +#include + +enum color { + BLACK = 0, + RED, + GREEN, + YELLOW, + BLUE, + PURPLE, + CYAN, + WHITE, +}; + + + +struct segment { + enum color c; + size_t len; + uint8_t *data; +}; + + +enum color next_color(void); +void color_put(enum color c); +void color_reset(void); +void cleanup_line(void); +void put_byte(uint8_t byte); +void flush_line(); +void add_segment(struct segment segment); +void write_chunk(uint8_t *buf, size_t len); +void write_chunk_s(uint8_t *buf, size_t len); + +#endif /* HEXDUMP_PRETTY_H */ diff --git a/ui.c b/ui.c index f114a41..9ac6965 100644 --- a/ui.c +++ b/ui.c @@ -11,12 +11,19 @@ #include -#define LINE_LEN 0x10 +#include "format.h" + +#define LINE_LEN 0x10 /* Number of bytes in a line */ + +#define LINENO_DIGITS 8 /* length of line numbers */ +#define LINENO_WIDTH (LINENO_DIGITS + 2) /* for padding */ + +#define INFO_HEIGHT 10 /* Height of the info panel */ // int screen_height, screen_width; struct screen { - WINDOW *lineno, *hex, *chr; + WINDOW *lineno, *hex, *chr, *info; int top_address; void *mem; size_t mem_len; @@ -32,47 +39,81 @@ void draw_lines() { } } -void draw_hex() { +void draw_hex(struct segment *current) { + for (int y = 0; y < LINES; y++) { for (int x = 0; x < LINE_LEN; x++) { + size_t addr = screen.top_address + y * LINE_LEN + x; + if (addr < 0 || addr >= screen.mem_len) continue; + if (current->start <= addr && addr < current->end) { + wattron(screen.hex, COLOR_PAIR(1)); + } if (screen.hy == y && screen.hx == x) { wattron(screen.hex, A_REVERSE); } mvwprintw(screen.hex, y, x * 2 + (x/2), "%02x", - 0xFF & ((char*) screen.mem)[screen.top_address + y * LINE_LEN + x]); + 0xFF & ((char*) screen.mem)[addr]); if (screen.hy == y && screen.hx == x) { wattroff(screen.hex, A_REVERSE); } + if (current->start <= addr && addr < current->end) { + wattroff(screen.hex, COLOR_PAIR(1)); + } } wrefresh(screen.hex); } } -void draw_chr() { +void draw_chr(struct segment *current) { for (int y = 0; y < LINES; y++) { for (int x = 0; x < LINE_LEN; x++) { + size_t addr = screen.top_address + y * LINE_LEN + x; + if (addr < 0 || addr >= screen.mem_len) continue; + if (current->start <= addr && addr < current->end) { + wattron(screen.chr, COLOR_PAIR(1)); + } if (screen.hy == y && screen.hx == x) { wattron(screen.chr, A_REVERSE); } - char c = ((char*) screen.mem)[screen.top_address + y * LINE_LEN + x]; + char c = ((char*) screen.mem)[addr]; mvwprintw(screen.chr, y, x, "%c", isprint(c) ? c : '.'); if (screen.hy == y && screen.hx == x) { wattroff(screen.chr, A_REVERSE); } + if (current->start <= addr && addr < current->end) { + wattroff(screen.chr, COLOR_PAIR(1)); + } } wrefresh(screen.chr); } } +void draw_info(struct segment *current) { + werase(screen.info); + wmove(screen.info, 0, 0); + whline(screen.info, '-', COLS); + + // size_t mem_addr = screen.top_address + screen.hy * LINE_LEN + screen.hx; + mvwprintw(screen.info, 1, 0, current->description); + + + wrefresh(screen.info); +} + void draw_screen() { + struct segment current = get_segment( + screen.mem, + screen.mem_len, + screen.top_address + screen.hy * LINE_LEN + screen.hx); draw_lines(); - draw_hex(); - draw_chr(); + draw_hex(¤t); + draw_chr(¤t); + draw_info(¤t); /* TODO end at end of file */ } -int main() { +int main(int argc, char *argv[]) { /* Terminal supporting mouse movements */ setenv("TERM", "xterm-1003", true); @@ -84,16 +125,28 @@ int main() { curs_set(0); start_color(); - - // getmaxyx(stdscr, screen_height, screen_width); + init_pair(1, COLOR_RED, COLOR_BLACK); keypad(stdscr, true); - screen.lineno = newwin(0, 10, 0, 0); - screen.hex = newwin(0, (int) ceil(LINE_LEN * 2.5), 0, 10); - screen.chr = newwin(0, LINE_LEN, 0, 10 + (int) ceil(LINE_LEN * 2.5)); + const int HEX_WIDTH = (int) ceil(LINE_LEN * 2.5); + + { + int h = LINES - INFO_HEIGHT; + screen.lineno = newwin(h, LINENO_WIDTH, 0, 0); + screen.hex = newwin(h, HEX_WIDTH, 0, LINENO_WIDTH); + screen.chr = newwin(h, LINE_LEN, 0, LINENO_WIDTH + HEX_WIDTH); + screen.info = newwin(0, 0, h, 0); + } + + char *filename; + if (argc == 1) { + filename = "payload.gz"; + } else { + filename = argv[1]; + } - int fd = open("payload.gz", O_RDONLY); + int fd = open(filename, O_RDONLY); struct stat statbuf; if (fstat(fd, &statbuf) == -1) { goto end; @@ -110,11 +163,11 @@ int main() { int ch; MEVENT event; - while (1) { + while (true) { ch = wgetch(stdscr); switch (ch) { case KEY_MOUSE: - wmove(stdscr, 0, 0); + // wmove(stdscr, 0, 0); switch (getmouse(&event)) { case OK: if (event.bstate & BUTTON4_PRESSED) { @@ -124,12 +177,17 @@ int main() { screen.top_address += LINE_LEN; } - if (event.x >= 10 && event.x < 10 + (int) ceil(LINE_LEN * 2.5)) { - screen.hx = (int) ((event.x - 10) / 2.5); - screen.hy = event.y; - } else if (event.x >= 10 + (int) ceil(LINE_LEN * 2.5) && event.x < (int) ceil(LINE_LEN * 2.5) + 10 + LINE_LEN) { - screen.hx = event.x - (10 + (int) ceil(LINE_LEN * 2.5)); - screen.hy = event.y; + if (event.y >= 0 && event.y < LINES - INFO_HEIGHT) { + if (event.x >= LINENO_WIDTH && event.x < LINENO_WIDTH + HEX_WIDTH) { + screen.hx = (int) ((event.x - LINENO_WIDTH) / 2.5); + screen.hy = event.y; + } else if (event.x >= LINENO_WIDTH + HEX_WIDTH && event.x < HEX_WIDTH + LINENO_WIDTH + LINE_LEN) { + screen.hx = event.x - (LINENO_WIDTH + HEX_WIDTH); + screen.hy = event.y; + } else { + screen.hx = -1; + screen.hy = -1; + } } else { screen.hx = -1; screen.hy = -1; @@ -141,16 +199,17 @@ int main() { // wprintw(win, "err"); break; } + draw_screen(); refresh(); break; case KEY_RESIZE: - wresize(screen.lineno, LINES, 0); - wresize(screen.hex, LINES, 0); - wresize(screen.chr, LINES, 0); + wresize(screen.lineno, LINES - INFO_HEIGHT, 0); + wresize(screen.hex, LINES - INFO_HEIGHT, 0); + wresize(screen.chr, LINES - INFO_HEIGHT, 0); draw_screen(); - mvprintw(0, 0, "%ix%i", COLS, LINES); - refresh(); + // mvprintw(0, 0, "%ix%i", COLS, LINES); + // refresh(); break; case KEY_ENTER: goto end; @@ -162,6 +221,7 @@ end: delwin(screen.lineno); delwin(screen.hex); delwin(screen.chr); + delwin(screen.info); endwin(); return 0; } -- cgit v1.2.3