diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-14 10:51:12 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-09-14 10:51:12 +0200 |
| commit | d54f58d487bfa5d6646d9a728d503351691081bf (patch) | |
| tree | 7e8b76263c6a70e3b26defc49677bce5227e3784 /miscutils | |
| parent | 363fb5ec4091120003b3f204996e7ff0aa354e58 (diff) | |
| download | busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.tar.gz busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.tar.bz2 busybox-w32-d54f58d487bfa5d6646d9a728d503351691081bf.zip | |
hexedit: implement "[enter] goto offset" key
This is a must if you need to edit sector 123456789999 on your /dev/disk.
text data bss dec hex filename
922745 481 6832 930058 e310a busybox_old
923023 481 6832 930336 e3220 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/hexedit.c | 79 | ||||
| -rw-r--r-- | miscutils/less.c | 4 |
2 files changed, 56 insertions, 27 deletions
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index b8627e826..eaf4ba57b 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c | |||
| @@ -17,7 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | #define ESC "\033" | 18 | #define ESC "\033" |
| 19 | #define HOME ESC"[H" | 19 | #define HOME ESC"[H" |
| 20 | #define CLEAR ESC"[H"ESC"[J" | 20 | #define CLEAR ESC"[J" |
| 21 | #define CLEAR_TILL_EOL ESC"[K" | ||
| 21 | #define SET_ALT_SCR ESC"[?1049h" | 22 | #define SET_ALT_SCR ESC"[?1049h" |
| 22 | #define POP_ALT_SCR ESC"[?1049l" | 23 | #define POP_ALT_SCR ESC"[?1049l" |
| 23 | 24 | ||
| @@ -30,7 +31,7 @@ struct globals { | |||
| 30 | int fd; | 31 | int fd; |
| 31 | unsigned height; | 32 | unsigned height; |
| 32 | unsigned row; | 33 | unsigned row; |
| 33 | uint8_t *addr; | 34 | uint8_t *baseaddr; |
| 34 | uint8_t *current_byte; | 35 | uint8_t *current_byte; |
| 35 | uint8_t *eof_byte; | 36 | uint8_t *eof_byte; |
| 36 | off_t size; | 37 | off_t size; |
| @@ -117,14 +118,15 @@ static void redraw(void) | |||
| 117 | { | 118 | { |
| 118 | uint8_t *data; | 119 | uint8_t *data; |
| 119 | off_t offset; | 120 | off_t offset; |
| 120 | unsigned i; | 121 | unsigned i, pos; |
| 121 | 122 | ||
| 122 | data = G.addr; | 123 | printf(HOME CLEAR); |
| 123 | offset = 0; | 124 | data = G.baseaddr; |
| 124 | i = 0; | 125 | offset = G.offset; |
| 126 | pos = i = 0; | ||
| 125 | while (i < G.height) { | 127 | while (i < G.height) { |
| 126 | char buf[LINEBUF_SIZE]; | 128 | char buf[LINEBUF_SIZE]; |
| 127 | format_line(buf, data, offset); | 129 | pos = format_line(buf, data, offset); |
| 128 | printf( | 130 | printf( |
| 129 | "\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */ | 131 | "\r\n%s" + (!i)*2, /* print \r\n only on 2nd line and later */ |
| 130 | buf | 132 | buf |
| @@ -133,6 +135,7 @@ static void redraw(void) | |||
| 133 | offset += 16; | 135 | offset += 16; |
| 134 | i++; | 136 | i++; |
| 135 | } | 137 | } |
| 138 | printf(ESC"[1;%uH", pos + 1); /* position on 1st hex byte in first line */ | ||
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | static void redraw_cur_line(void) | 141 | static void redraw_cur_line(void) |
| @@ -144,7 +147,7 @@ static void redraw_cur_line(void) | |||
| 144 | 147 | ||
| 145 | column = (0xf & (uintptr_t)G.current_byte); | 148 | column = (0xf & (uintptr_t)G.current_byte); |
| 146 | data = G.current_byte - column; | 149 | data = G.current_byte - column; |
| 147 | offset = G.offset + (data - G.addr); | 150 | offset = G.offset + (data - G.baseaddr); |
| 148 | 151 | ||
| 149 | column = column*3 + G.half; | 152 | column = column*3 + G.half; |
| 150 | column += format_line(buf, data, offset); | 153 | column += format_line(buf, data, offset); |
| @@ -158,28 +161,28 @@ static void redraw_cur_line(void) | |||
| 158 | 161 | ||
| 159 | static void remap(unsigned cur_pos) | 162 | static void remap(unsigned cur_pos) |
| 160 | { | 163 | { |
| 161 | if (G.addr) | 164 | if (G.baseaddr) |
| 162 | munmap(G.addr, G_mapsize); | 165 | munmap(G.baseaddr, G_mapsize); |
| 163 | 166 | ||
| 164 | G.addr = mmap(NULL, | 167 | G.baseaddr = mmap(NULL, |
| 165 | G_mapsize, | 168 | G_mapsize, |
| 166 | PROT_READ | PROT_WRITE, | 169 | PROT_READ | PROT_WRITE, |
| 167 | MAP_SHARED, | 170 | MAP_SHARED, |
| 168 | G.fd, | 171 | G.fd, |
| 169 | G.offset | 172 | G.offset |
| 170 | ); | 173 | ); |
| 171 | if (G.addr == MAP_FAILED) { | 174 | if (G.baseaddr == MAP_FAILED) { |
| 172 | restore_term(); | 175 | restore_term(); |
| 173 | bb_perror_msg_and_die("mmap"); | 176 | bb_perror_msg_and_die("mmap"); |
| 174 | } | 177 | } |
| 175 | 178 | ||
| 176 | G.current_byte = G.addr + cur_pos; | 179 | G.current_byte = G.baseaddr + cur_pos; |
| 177 | 180 | ||
| 178 | G.eof_byte = G.addr + G_mapsize; | 181 | G.eof_byte = G.baseaddr + G_mapsize; |
| 179 | if ((G.size - G.offset) < G_mapsize) { | 182 | if ((G.size - G.offset) < G_mapsize) { |
| 180 | /* mapping covers tail of the file */ | 183 | /* mapping covers tail of the file */ |
| 181 | /* we do have a mapped byte which is past eof */ | 184 | /* we do have a mapped byte which is past eof */ |
| 182 | G.eof_byte = G.addr + (G.size - G.offset); | 185 | G.eof_byte = G.baseaddr + (G.size - G.offset); |
| 183 | } | 186 | } |
| 184 | } | 187 | } |
| 185 | static void move_mapping_further(void) | 188 | static void move_mapping_further(void) |
| @@ -191,7 +194,7 @@ static void move_mapping_further(void) | |||
| 191 | return; /* can't move mapping even further, it's at the end already */ | 194 | return; /* can't move mapping even further, it's at the end already */ |
| 192 | 195 | ||
| 193 | pagesize = getpagesize(); /* constant on most arches */ | 196 | pagesize = getpagesize(); /* constant on most arches */ |
| 194 | pos = G.current_byte - G.addr; | 197 | pos = G.current_byte - G.baseaddr; |
| 195 | if (pos >= pagesize) { | 198 | if (pos >= pagesize) { |
| 196 | /* move offset up until current position is in 1st page */ | 199 | /* move offset up until current position is in 1st page */ |
| 197 | do { | 200 | do { |
| @@ -214,7 +217,7 @@ static void move_mapping_lower(void) | |||
| 214 | return; /* we are at 0 already */ | 217 | return; /* we are at 0 already */ |
| 215 | 218 | ||
| 216 | pagesize = getpagesize(); /* constant on most arches */ | 219 | pagesize = getpagesize(); /* constant on most arches */ |
| 217 | pos = G.current_byte - G.addr; | 220 | pos = G.current_byte - G.baseaddr; |
| 218 | 221 | ||
| 219 | /* move offset down until current position is in last page */ | 222 | /* move offset down until current position is in last page */ |
| 220 | pos += pagesize; | 223 | pos += pagesize; |
| @@ -252,18 +255,15 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
| 252 | G.size = xlseek(G.fd, 0, SEEK_END); | 255 | G.size = xlseek(G.fd, 0, SEEK_END); |
| 253 | 256 | ||
| 254 | /* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */ | 257 | /* TERMIOS_RAW_CRNL suppresses \n -> \r\n translation, helps with down-arrow */ |
| 258 | printf(SET_ALT_SCR); | ||
| 255 | set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL); | 259 | set_termios_to_raw(STDIN_FILENO, &G.orig_termios, TERMIOS_RAW_CRNL); |
| 256 | bb_signals(BB_FATAL_SIGS, sig_catcher); | 260 | bb_signals(BB_FATAL_SIGS, sig_catcher); |
| 257 | 261 | ||
| 258 | remap(0); | 262 | remap(0); |
| 259 | |||
| 260 | printf(SET_ALT_SCR); | ||
| 261 | redraw(); | 263 | redraw(); |
| 262 | printf(ESC"[1;10H"); /* position on 1st hex byte in first line */ | ||
| 263 | 264 | ||
| 264 | //TODO: //Home/End: start/end of line; '<'/'>': start/end of file | 265 | //TODO: //Home/End: start/end of line; '<'/'>': start/end of file |
| 265 | //Backspace: undo | 266 | //Backspace: undo |
| 266 | //Enter: goto specified position | ||
| 267 | //Ctrl-L: redraw | 267 | //Ctrl-L: redraw |
| 268 | //Ctrl-Z: suspend | 268 | //Ctrl-Z: suspend |
| 269 | //'/', Ctrl-S: search | 269 | //'/', Ctrl-S: search |
| @@ -367,9 +367,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
| 367 | } | 367 | } |
| 368 | if ((0xf & (uintptr_t)G.current_byte) == 0) { | 368 | if ((0xf & (uintptr_t)G.current_byte) == 0) { |
| 369 | /* leftmost pos, wrap to prev line */ | 369 | /* leftmost pos, wrap to prev line */ |
| 370 | if (G.current_byte == G.addr) { | 370 | if (G.current_byte == G.baseaddr) { |
| 371 | move_mapping_lower(); | 371 | move_mapping_lower(); |
| 372 | if (G.current_byte == G.addr) | 372 | if (G.current_byte == G.baseaddr) |
| 373 | break; /* first line, don't do anything */ | 373 | break; /* first line, don't do anything */ |
| 374 | } | 374 | } |
| 375 | G.half = 1; | 375 | G.half = 1; |
| @@ -385,9 +385,9 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
| 385 | cnt = G.height; | 385 | cnt = G.height; |
| 386 | case KEYCODE_UP: | 386 | case KEYCODE_UP: |
| 387 | k_up: | 387 | k_up: |
| 388 | if ((G.current_byte - G.addr) < 16) { | 388 | if ((G.current_byte - G.baseaddr) < 16) { |
| 389 | move_mapping_lower(); | 389 | move_mapping_lower(); |
| 390 | if ((G.current_byte - G.addr) < 16) | 390 | if ((G.current_byte - G.baseaddr) < 16) |
| 391 | break; | 391 | break; |
| 392 | } | 392 | } |
| 393 | G.current_byte -= 16; | 393 | G.current_byte -= 16; |
| @@ -403,6 +403,35 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) | |||
| 403 | if (--cnt) | 403 | if (--cnt) |
| 404 | goto k_up; | 404 | goto k_up; |
| 405 | break; | 405 | break; |
| 406 | |||
| 407 | case '\n': | ||
| 408 | case '\r': | ||
| 409 | /* [Enter]: goto specified position */ | ||
| 410 | { | ||
| 411 | char buf[sizeof(G.offset)*3 + 4]; | ||
| 412 | printf(ESC"[999;1H" CLEAR_TILL_EOL); /* go to last line */ | ||
| 413 | if (read_line_input(NULL, "Go to (dec,0Xhex,0oct): ", buf, sizeof(buf)) >= 0) { | ||
| 414 | off_t t; | ||
| 415 | unsigned pgmask; | ||
| 416 | |||
| 417 | t = bb_strtoull(buf, NULL, 0); | ||
| 418 | if (t >= G.size) | ||
| 419 | t = G.size - 1; | ||
| 420 | pgmask = getpagesize() - 1; | ||
| 421 | cnt = t & pgmask; | ||
| 422 | t = t & ~(off_t)pgmask; | ||
| 423 | if (t < 0) | ||
| 424 | cnt = t = 0; | ||
| 425 | G.offset = t; | ||
| 426 | remap(0); | ||
| 427 | redraw(); | ||
| 428 | cnt /= 16; | ||
| 429 | if (cnt) | ||
| 430 | goto k_down; | ||
| 431 | break; | ||
| 432 | } | ||
| 433 | /* EOF/error on input: fall through to exiting */ | ||
| 434 | } | ||
| 406 | case CTRL('X'): | 435 | case CTRL('X'): |
| 407 | restore_term(); | 436 | restore_term(); |
| 408 | return EXIT_SUCCESS; | 437 | return EXIT_SUCCESS; |
diff --git a/miscutils/less.c b/miscutils/less.c index f869a9e82..d524b6c87 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
| @@ -281,9 +281,9 @@ static void set_tty_cooked(void) | |||
| 281 | 281 | ||
| 282 | /* Move the cursor to a position (x,y), where (0,0) is the | 282 | /* Move the cursor to a position (x,y), where (0,0) is the |
| 283 | top-left corner of the console */ | 283 | top-left corner of the console */ |
| 284 | static void move_cursor(int line, int row) | 284 | static void move_cursor(int line, int col) |
| 285 | { | 285 | { |
| 286 | printf(ESC"[%u;%uH", line, row); | 286 | printf(ESC"[%u;%uH", line, col); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | static void clear_line(void) | 289 | static void clear_line(void) |
