diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-21 19:19:46 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-21 19:19:46 +0000 |
commit | 5592fac30812f3ca908961cd75a08a009baa7bb6 (patch) | |
tree | f9d2ab7fcb1188d0e0d387914ab025afcee2c433 | |
parent | 47bdb3ac482e8ccfa073b1c17fdf52d3721952b6 (diff) | |
download | busybox-w32-5592fac30812f3ca908961cd75a08a009baa7bb6.tar.gz busybox-w32-5592fac30812f3ca908961cd75a08a009baa7bb6.tar.bz2 busybox-w32-5592fac30812f3ca908961cd75a08a009baa7bb6.zip |
cmdedit: more optimizations
-rw-r--r-- | shell/cmdedit.c | 246 |
1 files changed, 109 insertions, 137 deletions
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 1143ded77..39cab19a0 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
@@ -119,14 +119,6 @@ static struct termios initial_settings, new_settings; | |||
119 | 119 | ||
120 | static | 120 | static |
121 | volatile unsigned cmdedit_termw = 80; /* actual terminal width */ | 121 | volatile unsigned cmdedit_termw = 80; /* actual terminal width */ |
122 | static | ||
123 | volatile int handlers_sets = 0; /* Set next bits: */ | ||
124 | enum { | ||
125 | SET_ATEXIT = 1, /* when atexit() has been called | ||
126 | and get euid,uid,gid to fast compare */ | ||
127 | SET_WCHG_HANDLERS = 2, /* winchg signal handler */ | ||
128 | SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */ | ||
129 | }; | ||
130 | 122 | ||
131 | 123 | ||
132 | static int cmdedit_x; /* real x terminal position */ | 124 | static int cmdedit_x; /* real x terminal position */ |
@@ -148,10 +140,6 @@ static char *user_buf = ""; | |||
148 | static char *home_pwd_buf = ""; | 140 | static char *home_pwd_buf = ""; |
149 | #endif | 141 | #endif |
150 | 142 | ||
151 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR || ENABLE_FEATURE_COMMAND_TAB_COMPLETION | ||
152 | static int my_euid; | ||
153 | #endif | ||
154 | |||
155 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION | 143 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION |
156 | static int my_uid; | 144 | static int my_uid; |
157 | static int my_gid; | 145 | static int my_gid; |
@@ -339,7 +327,6 @@ static void input_backspace(void) | |||
339 | } | 327 | } |
340 | } | 328 | } |
341 | 329 | ||
342 | |||
343 | /* Move forward one character */ | 330 | /* Move forward one character */ |
344 | static void input_forward(void) | 331 | static void input_forward(void) |
345 | { | 332 | { |
@@ -347,10 +334,21 @@ static void input_forward(void) | |||
347 | cmdedit_set_out_char(command_ps[cursor + 1]); | 334 | cmdedit_set_out_char(command_ps[cursor + 1]); |
348 | } | 335 | } |
349 | 336 | ||
337 | |||
350 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION | 338 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION |
351 | 339 | ||
352 | static char **matches; | 340 | static char **matches; |
353 | static int num_matches; | 341 | static unsigned num_matches; |
342 | |||
343 | static void free_tab_completion_data(void) | ||
344 | { | ||
345 | if (matches) { | ||
346 | while (num_matches) | ||
347 | free(matches[--num_matches]); | ||
348 | free(matches); | ||
349 | matches = NULL; | ||
350 | } | ||
351 | } | ||
354 | 352 | ||
355 | static void add_match(char *matched) | 353 | static void add_match(char *matched) |
356 | { | 354 | { |
@@ -363,7 +361,6 @@ static void add_match(char *matched) | |||
363 | } | 361 | } |
364 | 362 | ||
365 | #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION | 363 | #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION |
366 | |||
367 | static void username_tab_completion(char *ud, char *with_shash_flg) | 364 | static void username_tab_completion(char *ud, char *with_shash_flg) |
368 | { | 365 | { |
369 | struct passwd *entry; | 366 | struct passwd *entry; |
@@ -504,7 +501,6 @@ static void exe_n_cwd_tab_completion(char *command, int type) | |||
504 | } | 501 | } |
505 | 502 | ||
506 | for (i = 0; i < npaths; i++) { | 503 | for (i = 0; i < npaths; i++) { |
507 | |||
508 | dir = opendir(paths[i]); | 504 | dir = opendir(paths[i]); |
509 | if (!dir) /* Don't print an error */ | 505 | if (!dir) /* Don't print an error */ |
510 | continue; | 506 | continue; |
@@ -559,7 +555,6 @@ static void exe_n_cwd_tab_completion(char *command, int type) | |||
559 | } | 555 | } |
560 | } | 556 | } |
561 | 557 | ||
562 | |||
563 | #define QUOT (UCHAR_MAX+1) | 558 | #define QUOT (UCHAR_MAX+1) |
564 | 559 | ||
565 | #define collapse_pos(is, in) { \ | 560 | #define collapse_pos(is, in) { \ |
@@ -580,8 +575,8 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
580 | if (int_buf[i] == 0) { | 575 | if (int_buf[i] == 0) { |
581 | pos_buf[i] = -1; /* indicator end line */ | 576 | pos_buf[i] = -1; /* indicator end line */ |
582 | break; | 577 | break; |
583 | } else | 578 | } |
584 | pos_buf[i] = i; | 579 | pos_buf[i] = i; |
585 | } | 580 | } |
586 | 581 | ||
587 | /* mask \+symbol and convert '\t' to ' ' */ | 582 | /* mask \+symbol and convert '\t' to ' ' */ |
@@ -731,9 +726,9 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
731 | } | 726 | } |
732 | 727 | ||
733 | /* | 728 | /* |
734 | display by column original ideas from ls applet, | 729 | * display by column (original idea from ls applet, |
735 | very optimize by my :) | 730 | * very optimized by me :) |
736 | */ | 731 | */ |
737 | static void showfiles(void) | 732 | static void showfiles(void) |
738 | { | 733 | { |
739 | int ncols, row; | 734 | int ncols, row; |
@@ -770,11 +765,6 @@ static void showfiles(void) | |||
770 | } | 765 | } |
771 | } | 766 | } |
772 | 767 | ||
773 | static int match_compare(const void *a, const void *b) | ||
774 | { | ||
775 | return strcmp(*(char**)a, *(char**)b); | ||
776 | } | ||
777 | |||
778 | static char *add_quote_for_spec_chars(char *found) | 768 | static char *add_quote_for_spec_chars(char *found) |
779 | { | 769 | { |
780 | int l = 0; | 770 | int l = 0; |
@@ -789,18 +779,14 @@ static char *add_quote_for_spec_chars(char *found) | |||
789 | return s; | 779 | return s; |
790 | } | 780 | } |
791 | 781 | ||
782 | static int match_compare(const void *a, const void *b) | ||
783 | { | ||
784 | return strcmp(*(char**)a, *(char**)b); | ||
785 | } | ||
786 | |||
787 | /* Do TAB completion */ | ||
792 | static void input_tab(int *lastWasTab) | 788 | static void input_tab(int *lastWasTab) |
793 | { | 789 | { |
794 | /* Do TAB completion */ | ||
795 | if (lastWasTab == 0) { /* free all memory */ | ||
796 | if (matches) { | ||
797 | while (num_matches > 0) | ||
798 | free(matches[--num_matches]); | ||
799 | free(matches); | ||
800 | matches = (char **) NULL; | ||
801 | } | ||
802 | return; | ||
803 | } | ||
804 | if (!*lastWasTab) { | 790 | if (!*lastWasTab) { |
805 | char *tmp, *tmp1; | 791 | char *tmp, *tmp1; |
806 | int len_found; | 792 | int len_found; |
@@ -813,12 +799,12 @@ static void input_tab(int *lastWasTab) | |||
813 | /* Make a local copy of the string -- up | 799 | /* Make a local copy of the string -- up |
814 | * to the position of the cursor */ | 800 | * to the position of the cursor */ |
815 | tmp = strncpy(matchBuf, command_ps, cursor); | 801 | tmp = strncpy(matchBuf, command_ps, cursor); |
816 | tmp[cursor] = 0; | 802 | tmp[cursor] = '\0'; |
817 | 803 | ||
818 | find_type = find_match(matchBuf, &recalc_pos); | 804 | find_type = find_match(matchBuf, &recalc_pos); |
819 | 805 | ||
820 | /* Free up any memory already allocated */ | 806 | /* Free up any memory already allocated */ |
821 | input_tab(0); | 807 | free_tab_completion_data(); |
822 | 808 | ||
823 | #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION | 809 | #if ENABLE_FEATURE_COMMAND_USERNAME_COMPLETION |
824 | /* If the word starts with `~' and there is no slash in the word, | 810 | /* If the word starts with `~' and there is no slash in the word, |
@@ -829,24 +815,24 @@ static void input_tab(int *lastWasTab) | |||
829 | if (!matches) | 815 | if (!matches) |
830 | #endif | 816 | #endif |
831 | /* Try to match any executable in our path and everything | 817 | /* Try to match any executable in our path and everything |
832 | * in the current working directory that matches. */ | 818 | * in the current working directory */ |
833 | exe_n_cwd_tab_completion(matchBuf, find_type); | 819 | exe_n_cwd_tab_completion(matchBuf, find_type); |
834 | /* Sort, then remove any duplicates found */ | 820 | /* Sort, then remove any duplicates found */ |
835 | if (matches) { | 821 | if (matches) { |
836 | int i, n = 0; | 822 | int i, n = 0; |
837 | qsort(matches, num_matches, sizeof(char*), match_compare); | 823 | qsort(matches, num_matches, sizeof(char*), match_compare); |
838 | for (i = 0; i < num_matches - 1; ++i) { | 824 | for (i = 0; i < num_matches - 1; ++i) { |
839 | if (matches[i] && matches[i+1]) { | 825 | if (matches[i] && matches[i+1]) { /* paranoia */ |
840 | if (strcmp(matches[i], matches[i+1]) == 0) { | 826 | if (strcmp(matches[i], matches[i+1]) == 0) { |
841 | free(matches[i]); | 827 | free(matches[i]); |
842 | matches[i] = 0; | 828 | matches[i] = NULL; /* paranoia */ |
843 | } else { | 829 | } else { |
844 | matches[n++] = matches[i]; | 830 | matches[n++] = matches[i]; |
845 | } | 831 | } |
846 | } | 832 | } |
847 | } | 833 | } |
848 | matches[n++] = matches[num_matches-1]; | 834 | matches[n] = matches[i]; |
849 | num_matches = n; | 835 | num_matches = n + 1; |
850 | } | 836 | } |
851 | /* Did we find exactly one match? */ | 837 | /* Did we find exactly one match? */ |
852 | if (!matches || num_matches > 1) { | 838 | if (!matches || num_matches > 1) { |
@@ -858,10 +844,10 @@ static void input_tab(int *lastWasTab) | |||
858 | for (tmp = tmp1; *tmp; tmp++) | 844 | for (tmp = tmp1; *tmp; tmp++) |
859 | for (len_found = 1; len_found < num_matches; len_found++) | 845 | for (len_found = 1; len_found < num_matches; len_found++) |
860 | if (matches[len_found][(tmp - tmp1)] != *tmp) { | 846 | if (matches[len_found][(tmp - tmp1)] != *tmp) { |
861 | *tmp = 0; | 847 | *tmp = '\0'; |
862 | break; | 848 | break; |
863 | } | 849 | } |
864 | if (*tmp1 == 0) { /* have unique */ | 850 | if (*tmp1 == '\0') { /* have unique */ |
865 | free(tmp1); | 851 | free(tmp1); |
866 | return; | 852 | return; |
867 | } | 853 | } |
@@ -881,7 +867,6 @@ static void input_tab(int *lastWasTab) | |||
881 | len_found = strlen(tmp); | 867 | len_found = strlen(tmp); |
882 | /* have space to placed match? */ | 868 | /* have space to placed match? */ |
883 | if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { | 869 | if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { |
884 | |||
885 | /* before word for match */ | 870 | /* before word for match */ |
886 | command_ps[cursor - recalc_pos] = 0; | 871 | command_ps[cursor - recalc_pos] = 0; |
887 | /* save tail line */ | 872 | /* save tail line */ |
@@ -914,6 +899,7 @@ static void input_tab(int *lastWasTab) | |||
914 | } | 899 | } |
915 | } | 900 | } |
916 | } | 901 | } |
902 | |||
917 | #endif /* FEATURE_COMMAND_TAB_COMPLETION */ | 903 | #endif /* FEATURE_COMMAND_TAB_COMPLETION */ |
918 | 904 | ||
919 | 905 | ||
@@ -927,7 +913,7 @@ static int cur_history; | |||
927 | 913 | ||
928 | static void get_previous_history(void) | 914 | static void get_previous_history(void) |
929 | { | 915 | { |
930 | if (command_ps[0] != 0 || history[cur_history] == 0) { | 916 | if (command_ps[0] != '\0' || history[cur_history] == NULL) { |
931 | free(history[cur_history]); | 917 | free(history[cur_history]); |
932 | history[cur_history] = xstrdup(command_ps); | 918 | history[cur_history] = xstrdup(command_ps); |
933 | } | 919 | } |
@@ -1126,81 +1112,6 @@ enum { vi_mode = 0 }; | |||
1126 | * cmdedit_read_input and its helpers | 1112 | * cmdedit_read_input and its helpers |
1127 | */ | 1113 | */ |
1128 | 1114 | ||
1129 | #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) | ||
1130 | #define getTermSettings(fd, argp) tcgetattr(fd, argp); | ||
1131 | |||
1132 | static sighandler_t previous_SIGWINCH_handler; | ||
1133 | |||
1134 | static void cmdedit_reset_term(void) | ||
1135 | { | ||
1136 | if (handlers_sets & SET_RESET_TERM) { | ||
1137 | setTermSettings(STDIN_FILENO, (void *) &initial_settings); | ||
1138 | handlers_sets &= ~SET_RESET_TERM; | ||
1139 | } | ||
1140 | if (handlers_sets & SET_WCHG_HANDLERS) { | ||
1141 | /* restore SIGWINCH handler */ | ||
1142 | signal(SIGWINCH, previous_SIGWINCH_handler); | ||
1143 | handlers_sets &= ~SET_WCHG_HANDLERS; | ||
1144 | } | ||
1145 | fflush(stdout); | ||
1146 | } | ||
1147 | |||
1148 | static void cmdedit_setwidth(unsigned w, int redraw_flg) | ||
1149 | { | ||
1150 | cmdedit_termw = w; | ||
1151 | if (redraw_flg) { | ||
1152 | /* new y for current cursor */ | ||
1153 | int new_y = (cursor + cmdedit_prmt_len) / w; | ||
1154 | /* redraw */ | ||
1155 | redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); | ||
1156 | fflush(stdout); | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | static void win_changed(int nsig) | ||
1161 | { | ||
1162 | int width; | ||
1163 | get_terminal_width_height(0, &width, NULL); | ||
1164 | cmdedit_setwidth(width, nsig /* - just a yes/no flag */); | ||
1165 | if (nsig == SIGWINCH) | ||
1166 | signal(SIGWINCH, win_changed); /* rearm ourself */ | ||
1167 | } | ||
1168 | |||
1169 | static void cmdedit_init(void) | ||
1170 | { | ||
1171 | cmdedit_prmt_len = 0; | ||
1172 | if (!(handlers_sets & SET_WCHG_HANDLERS)) { | ||
1173 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | ||
1174 | win_changed(0); /* do initial resizing */ | ||
1175 | handlers_sets |= SET_WCHG_HANDLERS; | ||
1176 | } | ||
1177 | |||
1178 | if (!(handlers_sets & SET_ATEXIT)) { | ||
1179 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR | ||
1180 | struct passwd *entry; | ||
1181 | |||
1182 | my_euid = geteuid(); | ||
1183 | entry = getpwuid(my_euid); | ||
1184 | if (entry) { | ||
1185 | user_buf = xstrdup(entry->pw_name); | ||
1186 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
1187 | } | ||
1188 | #endif | ||
1189 | |||
1190 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION | ||
1191 | |||
1192 | #if !ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR | ||
1193 | my_euid = geteuid(); | ||
1194 | #endif | ||
1195 | my_uid = getuid(); | ||
1196 | my_gid = getgid(); | ||
1197 | #endif /* FEATURE_COMMAND_TAB_COMPLETION */ | ||
1198 | handlers_sets |= SET_ATEXIT; | ||
1199 | // Crap. We should be able to do it without atexit. | ||
1200 | atexit(cmdedit_reset_term); /* be sure to do this only once */ | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | #if !ENABLE_FEATURE_SH_FANCY_PROMPT | 1115 | #if !ENABLE_FEATURE_SH_FANCY_PROMPT |
1205 | static void parse_prompt(const char *prmt_ptr) | 1116 | static void parse_prompt(const char *prmt_ptr) |
1206 | { | 1117 | { |
@@ -1259,7 +1170,7 @@ static void parse_prompt(const char *prmt_ptr) | |||
1259 | } | 1170 | } |
1260 | break; | 1171 | break; |
1261 | case '$': | 1172 | case '$': |
1262 | c = (my_euid == 0 ? '#' : '$'); | 1173 | c = (geteuid() == 0 ? '#' : '$'); |
1263 | break; | 1174 | break; |
1264 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR | 1175 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR |
1265 | case 'w': | 1176 | case 'w': |
@@ -1283,7 +1194,8 @@ static void parse_prompt(const char *prmt_ptr) | |||
1283 | pbuf += (cp-pbuf) + 1; | 1194 | pbuf += (cp-pbuf) + 1; |
1284 | break; | 1195 | break; |
1285 | case '!': | 1196 | case '!': |
1286 | snprintf(pbuf = buf2, sizeof(buf2), "%d", num_ok_lines); | 1197 | pbuf = buf2; |
1198 | snprintf(buf2, sizeof(buf2), "%d", num_ok_lines); | ||
1287 | break; | 1199 | break; |
1288 | case 'e': case 'E': /* \e \E = \033 */ | 1200 | case 'e': case 'E': /* \e \E = \033 */ |
1289 | c = '\033'; | 1201 | c = '\033'; |
@@ -1330,11 +1242,71 @@ static void parse_prompt(const char *prmt_ptr) | |||
1330 | } | 1242 | } |
1331 | #endif | 1243 | #endif |
1332 | 1244 | ||
1245 | #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) | ||
1246 | #define getTermSettings(fd, argp) tcgetattr(fd, argp); | ||
1247 | |||
1248 | static sighandler_t previous_SIGWINCH_handler; | ||
1249 | |||
1250 | static void cmdedit_reset_term(void) | ||
1251 | { | ||
1252 | setTermSettings(STDIN_FILENO, (void *) &initial_settings); | ||
1253 | /* restore SIGWINCH handler */ | ||
1254 | signal(SIGWINCH, previous_SIGWINCH_handler); | ||
1255 | fflush(stdout); | ||
1256 | } | ||
1257 | |||
1258 | static void cmdedit_setwidth(unsigned w, int redraw_flg) | ||
1259 | { | ||
1260 | cmdedit_termw = w; | ||
1261 | if (redraw_flg) { | ||
1262 | /* new y for current cursor */ | ||
1263 | int new_y = (cursor + cmdedit_prmt_len) / w; | ||
1264 | /* redraw */ | ||
1265 | redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); | ||
1266 | fflush(stdout); | ||
1267 | } | ||
1268 | } | ||
1269 | |||
1270 | static void win_changed(int nsig) | ||
1271 | { | ||
1272 | int width; | ||
1273 | get_terminal_width_height(0, &width, NULL); | ||
1274 | cmdedit_setwidth(width, nsig /* - just a yes/no flag */); | ||
1275 | if (nsig == SIGWINCH) | ||
1276 | signal(SIGWINCH, win_changed); /* rearm ourself */ | ||
1277 | } | ||
1278 | |||
1279 | static void cmdedit_init(void) | ||
1280 | { | ||
1281 | cmdedit_prmt_len = 0; | ||
1282 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | ||
1283 | win_changed(0); /* do initial resizing */ | ||
1284 | |||
1285 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR | ||
1286 | { | ||
1287 | struct passwd *entry; | ||
1288 | |||
1289 | entry = getpwuid(geteuid()); | ||
1290 | if (entry) { | ||
1291 | user_buf = xstrdup(entry->pw_name); | ||
1292 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
1293 | } | ||
1294 | } | ||
1295 | #endif | ||
1296 | |||
1297 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION | ||
1298 | my_uid = getuid(); | ||
1299 | my_gid = getgid(); | ||
1300 | #endif | ||
1301 | // Crap. We should be able to do it without atexit. | ||
1302 | atexit(cmdedit_reset_term); /* be sure to do this only once */ | ||
1303 | } | ||
1304 | |||
1333 | /* | 1305 | /* |
1334 | * the emacs and vi modes share much of the code in the big | 1306 | * The emacs and vi modes share much of the code in the big |
1335 | * command loop. commands entered when in vi's command mode (aka | 1307 | * command loop. Commands entered when in vi's command mode (aka |
1336 | * "escape mode") get an extra bit added to distinguish them -- | 1308 | * "escape mode") get an extra bit added to distinguish them -- |
1337 | * this keeps them from being self-inserted. this clutters the | 1309 | * this keeps them from being self-inserted. This clutters the |
1338 | * big switch a bit, but keeps all the code in one place. | 1310 | * big switch a bit, but keeps all the code in one place. |
1339 | */ | 1311 | */ |
1340 | 1312 | ||
@@ -1379,7 +1351,6 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
1379 | #endif | 1351 | #endif |
1380 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 1352 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
1381 | setTermSettings(0, (void *) &new_settings); | 1353 | setTermSettings(0, (void *) &new_settings); |
1382 | handlers_sets |= SET_RESET_TERM; | ||
1383 | 1354 | ||
1384 | /* Now initialize things */ | 1355 | /* Now initialize things */ |
1385 | cmdedit_init(); | 1356 | cmdedit_init(); |
@@ -1387,11 +1358,12 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
1387 | parse_prompt(prompt); | 1358 | parse_prompt(prompt); |
1388 | 1359 | ||
1389 | while (1) { | 1360 | while (1) { |
1390 | fflush(stdout); /* buffered out to fast */ | 1361 | fflush(stdout); |
1391 | 1362 | ||
1392 | if (safe_read(0, &c, 1) < 1) | 1363 | if (safe_read(0, &c, 1) < 1) { |
1393 | /* if we can't read input then exit */ | 1364 | /* if we can't read input then exit */ |
1394 | goto prepare_to_die; | 1365 | goto prepare_to_die; |
1366 | } | ||
1395 | 1367 | ||
1396 | ic = c; | 1368 | ic = c; |
1397 | 1369 | ||
@@ -1789,23 +1761,22 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
1789 | lastWasTab = FALSE; | 1761 | lastWasTab = FALSE; |
1790 | } | 1762 | } |
1791 | 1763 | ||
1792 | setTermSettings(0, (void *) &initial_settings); | ||
1793 | handlers_sets &= ~SET_RESET_TERM; | ||
1794 | |||
1795 | #if MAX_HISTORY > 0 | 1764 | #if MAX_HISTORY > 0 |
1796 | /* Handle command history log */ | 1765 | /* Handle command history log */ |
1797 | /* cleanup may be saved current command line */ | 1766 | /* cleanup may be saved current command line */ |
1798 | if (len > 0) { /* no put empty line */ | 1767 | if (len > 0) { |
1799 | int i = n_history; | 1768 | int i = n_history; |
1800 | 1769 | ||
1801 | free(history[MAX_HISTORY]); | 1770 | free(history[MAX_HISTORY]); |
1802 | history[MAX_HISTORY] = 0; | 1771 | history[MAX_HISTORY] = NULL; |
1803 | /* After max history, remove the oldest command */ | 1772 | /* After max history, remove the oldest command */ |
1804 | if (i >= MAX_HISTORY) { | 1773 | if (i >= MAX_HISTORY) { |
1805 | free(history[0]); | 1774 | free(history[0]); |
1806 | for (i = 0; i < MAX_HISTORY-1; i++) | 1775 | for (i = 0; i < MAX_HISTORY-1; i++) |
1807 | history[i] = history[i+1]; | 1776 | history[i] = history[i+1]; |
1808 | } | 1777 | } |
1778 | // Maybe "if (!i || strcmp(history[i-1], command) != 0) ..." | ||
1779 | // (i.e. do not save dups?) | ||
1809 | history[i++] = xstrdup(command); | 1780 | history[i++] = xstrdup(command); |
1810 | cur_history = i; | 1781 | cur_history = i; |
1811 | n_history = i; | 1782 | n_history = i; |
@@ -1822,12 +1793,13 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
1822 | } | 1793 | } |
1823 | 1794 | ||
1824 | #if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION | 1795 | #if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_COMMAND_TAB_COMPLETION |
1825 | input_tab(0); | 1796 | free_tab_completion_data(); |
1826 | #endif | 1797 | #endif |
1827 | 1798 | ||
1828 | #if ENABLE_FEATURE_SH_FANCY_PROMPT | 1799 | #if ENABLE_FEATURE_SH_FANCY_PROMPT |
1829 | free(cmdedit_prompt); | 1800 | free(cmdedit_prompt); |
1830 | #endif | 1801 | #endif |
1802 | /* restore initial_settings and SIGWINCH handler */ | ||
1831 | cmdedit_reset_term(); | 1803 | cmdedit_reset_term(); |
1832 | return len; | 1804 | return len; |
1833 | } | 1805 | } |