aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-11-10 01:35:47 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-11-10 01:35:47 +0000
commit73cb1fdfea01a5b16d906285275fa3805cac01a3 (patch)
tree1f8753aabd27cf20c73b9b58240bc47e6e70dc04 /libbb/lineedit.c
parente7fca5125a1e683a8f92e988b6218da63a620f7a (diff)
downloadbusybox-w32-73cb1fdfea01a5b16d906285275fa3805cac01a3.tar.gz
busybox-w32-73cb1fdfea01a5b16d906285275fa3805cac01a3.tar.bz2
busybox-w32-73cb1fdfea01a5b16d906285275fa3805cac01a3.zip
lineedit: stop using both data/bss and tons of stack.
stack usage was ~10 kb! unfortunately, noticeable code size growth: text data bss dec hex filename 9252 12 181 9445 24e5 busybox.t7/libbb/lineedit.o 9714 4 0 9718 25f6 busybox.t8/libbb/lineedit.o
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c259
1 files changed, 166 insertions, 93 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index f65e852b1..4d33834ce 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -41,7 +41,6 @@
41#define ENABLE_FEATURE_TAB_COMPLETION 0 41#define ENABLE_FEATURE_TAB_COMPLETION 0
42#define ENABLE_FEATURE_USERNAME_COMPLETION 0 42#define ENABLE_FEATURE_USERNAME_COMPLETION 0
43#define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0 43#define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0
44#define ENABLE_FEATURE_CLEAN_UP 0
45 44
46#endif /* TEST */ 45#endif /* TEST */
47 46
@@ -56,35 +55,117 @@
56#endif 55#endif
57 56
58#define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \ 57#define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \
59(ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) 58 (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT)
59#define USE_FEATURE_GETUSERNAME_AND_HOMEDIR(...)
60#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
61#undef USE_FEATURE_GETUSERNAME_AND_HOMEDIR
62#define USE_FEATURE_GETUSERNAME_AND_HOMEDIR(...) __VA_ARGS__
63#endif
60 64
61enum { MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN }; 65enum {
66 /* We use int16_t for positions, need to limit line len */
67 MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0
68 ? CONFIG_FEATURE_EDITING_MAX_LEN
69 : 0x7ff0
70};
71
72#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
73static const char null_str[] ALIGN1 = "";
74#endif
62 75
63static line_input_t *state; 76/* We try to minimize both static and stack usage. */
77struct statics {
78 line_input_t *state;
64 79
65static struct termios initial_settings, new_settings; 80 volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
81 sighandler_t previous_SIGWINCH_handler;
66 82
67static volatile unsigned cmdedit_termw = 80; /* actual terminal width */
68 83
69static int cmdedit_x; /* real x terminal position */ 84 int cmdedit_x; /* real x terminal position */
70static int cmdedit_y; /* pseudoreal y terminal position */ 85 int cmdedit_y; /* pseudoreal y terminal position */
71static int cmdedit_prmt_len; /* length of prompt (without colors etc) */ 86 int cmdedit_prmt_len; /* length of prompt (without colors etc) */
72 87
73static unsigned cursor; 88 unsigned cursor;
74static unsigned command_len; 89 unsigned command_len;
75static char *command_ps; 90 char *command_ps;
76static const char *cmdedit_prompt;
77 91
92 const char *cmdedit_prompt;
78#if ENABLE_FEATURE_EDITING_FANCY_PROMPT 93#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
79static char *hostname_buf; 94 char *hostname_buf;
80static int num_ok_lines = 1; 95 int num_ok_lines; /* = 1; */
96#endif
97
98#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
99 char *user_buf;
100 char *home_pwd_buf; /* = (char*)null_str; */
101#endif
102
103#if ENABLE_FEATURE_TAB_COMPLETION
104 char **matches;
105 unsigned num_matches;
81#endif 106#endif
82 107
108#if ENABLE_FEATURE_EDITING_VI
109#define DELBUFSIZ 128
110 char *delptr;
111 smallint newdelflag; /* whether delbuf should be reused yet */
112 char delbuf[DELBUFSIZ]; /* a place to store deleted characters */
113#endif
114
115 /* Formerly these were big buffers on stack: */
116#if ENABLE_FEATURE_TAB_COMPLETION
117 char exe_n_cwd_tab_completion__dirbuf[MAX_LINELEN];
118 char input_tab__matchBuf[MAX_LINELEN];
119 int16_t find_match__int_buf[MAX_LINELEN + 1]; /* need to have 9 bits at least */
120 int16_t find_match__pos_buf[MAX_LINELEN + 1];
121#endif
122};
123
124static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
125
126#define S (*ptr_to_statics)
127#define state (S.state )
128#define cmdedit_termw (S.cmdedit_termw )
129#define previous_SIGWINCH_handler (S.previous_SIGWINCH_handler)
130#define cmdedit_x (S.cmdedit_x )
131#define cmdedit_y (S.cmdedit_y )
132#define cmdedit_prmt_len (S.cmdedit_prmt_len)
133#define cursor (S.cursor )
134#define command_len (S.command_len )
135#define command_ps (S.command_ps )
136#define cmdedit_prompt (S.cmdedit_prompt )
137#define hostname_buf (S.hostname_buf )
138#define num_ok_lines (S.num_ok_lines )
139#define user_buf (S.user_buf )
140#define home_pwd_buf (S.home_pwd_buf )
141#define matches (S.matches )
142#define num_matches (S.num_matches )
143#define delptr (S.delptr )
144#define newdelflag (S.newdelflag )
145#define delbuf (S.delbuf )
146
147#define INIT_S() do { \
148 (*(struct statics**)&ptr_to_statics) = xzalloc(sizeof(S)); \
149 cmdedit_termw = 80; \
150 USE_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \
151 USE_FEATURE_GETUSERNAME_AND_HOMEDIR(home_pwd_buf = (char*)null_str;) \
152} while (0)
153static void deinit_S(void)
154{
155#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
156 free(hostname_buf);
157 /* This one is allocated only if FANCY_PROMPT is on
158 * (otherwise it points to verbatim prompt (NOT malloced) */
159 free((char*)cmdedit_prompt);
160#endif
83#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR 161#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
84static const char null_str[] = ""; 162 free(user_buf);
85static char *user_buf; 163 if (home_pwd_buf != null_str)
86static char *home_pwd_buf = (char*)null_str; 164 free(home_pwd_buf);
87#endif 165#endif
166 free(ptr_to_statics);
167}
168#define DEINIT_S() deinit_S()
88 169
89/* Put 'command_ps[cursor]', cursor++. 170/* Put 'command_ps[cursor]', cursor++.
90 * Advance cursor on screen. If we reached right margin, scroll text up 171 * Advance cursor on screen. If we reached right margin, scroll text up
@@ -110,8 +191,7 @@ static void cmdedit_set_out_char(int next_char)
110 } else 191 } else
111#endif 192#endif
112 { 193 {
113 if (initial_settings.c_lflag & ECHO) 194 bb_putchar(c);
114 bb_putchar(c);
115 } 195 }
116 if (++cmdedit_x >= cmdedit_termw) { 196 if (++cmdedit_x >= cmdedit_termw) {
117 /* terminal is scrolled down */ 197 /* terminal is scrolled down */
@@ -204,13 +284,6 @@ static void redraw(int y, int back_cursor)
204 input_backward(back_cursor); 284 input_backward(back_cursor);
205} 285}
206 286
207#if ENABLE_FEATURE_EDITING_VI
208#define DELBUFSIZ 128
209static char *delbuf; /* a (malloced) place to store deleted characters */
210static char *delp;
211static char newdelflag; /* whether delbuf should be reused yet */
212#endif
213
214/* Delete the char in front of the cursor, optionally saving it 287/* Delete the char in front of the cursor, optionally saving it
215 * for later putback */ 288 * for later putback */
216static void input_delete(int save) 289static void input_delete(int save)
@@ -223,14 +296,11 @@ static void input_delete(int save)
223#if ENABLE_FEATURE_EDITING_VI 296#if ENABLE_FEATURE_EDITING_VI
224 if (save) { 297 if (save) {
225 if (newdelflag) { 298 if (newdelflag) {
226 if (!delbuf) 299 delptr = delbuf;
227 delbuf = malloc(DELBUFSIZ);
228 /* safe if malloc fails */
229 delp = delbuf;
230 newdelflag = 0; 300 newdelflag = 0;
231 } 301 }
232 if (delbuf && (delp - delbuf < DELBUFSIZ)) 302 if ((delptr - delbuf) < DELBUFSIZ)
233 *delp++ = command_ps[j]; 303 *delptr++ = command_ps[j];
234 } 304 }
235#endif 305#endif
236 306
@@ -245,7 +315,7 @@ static void input_delete(int save)
245static void put(void) 315static void put(void)
246{ 316{
247 int ocursor; 317 int ocursor;
248 int j = delp - delbuf; 318 int j = delptr - delbuf;
249 319
250 if (j == 0) 320 if (j == 0)
251 return; 321 return;
@@ -275,12 +345,8 @@ static void input_forward(void)
275 cmdedit_set_out_char(command_ps[cursor + 1]); 345 cmdedit_set_out_char(command_ps[cursor + 1]);
276} 346}
277 347
278
279#if ENABLE_FEATURE_TAB_COMPLETION 348#if ENABLE_FEATURE_TAB_COMPLETION
280 349
281static char **matches;
282static unsigned num_matches;
283
284static void free_tab_completion_data(void) 350static void free_tab_completion_data(void)
285{ 351{
286 if (matches) { 352 if (matches) {
@@ -329,11 +395,8 @@ static void username_tab_completion(char *ud, char *with_shash_flg)
329 } 395 }
330 if (home) { 396 if (home) {
331 if ((userlen + strlen(home) + 1) < MAX_LINELEN) { 397 if ((userlen + strlen(home) + 1) < MAX_LINELEN) {
332 char temp2[MAX_LINELEN]; /* argument size */
333
334 /* /home/user/... */ 398 /* /home/user/... */
335 sprintf(temp2, "%s%s", home, ud); 399 sprintf(sav_ud, "%s%s", home, ud);
336 strcpy(sav_ud, temp2);
337 } 400 }
338 } 401 }
339 } else { 402 } else {
@@ -411,7 +474,6 @@ static void exe_n_cwd_tab_completion(char *command, int type)
411{ 474{
412 DIR *dir; 475 DIR *dir;
413 struct dirent *next; 476 struct dirent *next;
414 char dirbuf[MAX_LINELEN];
415 struct stat st; 477 struct stat st;
416 char *path1[1]; 478 char *path1[1];
417 char **paths = path1; 479 char **paths = path1;
@@ -419,6 +481,8 @@ static void exe_n_cwd_tab_completion(char *command, int type)
419 int i; 481 int i;
420 char *found; 482 char *found;
421 char *pfind = strrchr(command, '/'); 483 char *pfind = strrchr(command, '/');
484/* char dirbuf[MAX_LINELEN]; */
485#define dirbuf (S.exe_n_cwd_tab_completion__dirbuf)
422 486
423 npaths = 1; 487 npaths = 1;
424 path1[0] = (char*)"."; 488 path1[0] = (char*)".";
@@ -492,21 +556,25 @@ static void exe_n_cwd_tab_completion(char *command, int type)
492 free(paths[0]); /* allocated memory only in first member */ 556 free(paths[0]); /* allocated memory only in first member */
493 free(paths); 557 free(paths);
494 } 558 }
559#undef dirbuf
495} 560}
496 561
497#define QUOT (UCHAR_MAX+1) 562#define QUOT (UCHAR_MAX+1)
498 563
499#define collapse_pos(is, in) { \ 564#define collapse_pos(is, in) do { \
500 memmove(int_buf+(is), int_buf+(in), (MAX_LINELEN+1-(is)-(in))*sizeof(int)); \ 565 memmove(int_buf+(is), int_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \
501 memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in))*sizeof(int)); } 566 memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \
567} while (0)
502 568
503static int find_match(char *matchBuf, int *len_with_quotes) 569static int find_match(char *matchBuf, int *len_with_quotes)
504{ 570{
505 int i, j; 571 int i, j;
506 int command_mode; 572 int command_mode;
507 int c, c2; 573 int c, c2;
508 int int_buf[MAX_LINELEN + 1]; 574/* int16_t int_buf[MAX_LINELEN + 1]; */
509 int pos_buf[MAX_LINELEN + 1]; 575/* int16_t pos_buf[MAX_LINELEN + 1]; */
576#define int_buf (S.find_match__int_buf)
577#define pos_buf (S.find_match__pos_buf)
510 578
511 /* set to integer dimension characters and own positions */ 579 /* set to integer dimension characters and own positions */
512 for (i = 0;; i++) { 580 for (i = 0;; i++) {
@@ -622,8 +690,8 @@ static int find_match(char *matchBuf, int *len_with_quotes)
622 for (i = 0; int_buf[i]; i++) 690 for (i = 0; int_buf[i]; i++)
623 if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { 691 if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') {
624 if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY 692 if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY
625 && matchBuf[pos_buf[0]]=='c' 693 && matchBuf[pos_buf[0]] == 'c'
626 && matchBuf[pos_buf[1]]=='d' 694 && matchBuf[pos_buf[1]] == 'd'
627 ) { 695 ) {
628 command_mode = FIND_DIR_ONLY; 696 command_mode = FIND_DIR_ONLY;
629 } else { 697 } else {
@@ -657,11 +725,13 @@ static int find_match(char *matchBuf, int *len_with_quotes)
657 matchBuf[c++] = matchBuf[pos_buf[i]]; 725 matchBuf[c++] = matchBuf[pos_buf[i]];
658 j = pos_buf[i] + 1; 726 j = pos_buf[i] + 1;
659 } 727 }
660 matchBuf[c] = 0; 728 matchBuf[c] = '\0';
661 /* old length matchBuf with quotes symbols */ 729 /* old length matchBuf with quotes symbols */
662 *len_with_quotes = j ? j - pos_buf[0] : 0; 730 *len_with_quotes = j ? j - pos_buf[0] : 0;
663 731
664 return command_mode; 732 return command_mode;
733#undef int_buf
734#undef pos_buf
665} 735}
666 736
667/* 737/*
@@ -724,7 +794,7 @@ static int match_compare(const void *a, const void *b)
724} 794}
725 795
726/* Do TAB completion */ 796/* Do TAB completion */
727static void input_tab(int *lastWasTab) 797static void input_tab(smallint *lastWasTab)
728{ 798{
729 if (!(state->flags & TAB_COMPLETION)) 799 if (!(state->flags & TAB_COMPLETION))
730 return; 800 return;
@@ -732,7 +802,8 @@ static void input_tab(int *lastWasTab)
732 if (!*lastWasTab) { 802 if (!*lastWasTab) {
733 char *tmp, *tmp1; 803 char *tmp, *tmp1;
734 int len_found; 804 int len_found;
735 char matchBuf[MAX_LINELEN]; 805/* char matchBuf[MAX_LINELEN]; */
806#define matchBuf (S.input_tab__matchBuf)
736 int find_type; 807 int find_type;
737 int recalc_pos; 808 int recalc_pos;
738 809
@@ -782,7 +853,6 @@ static void input_tab(int *lastWasTab)
782 if (!matches) 853 if (!matches)
783 return; /* not found */ 854 return; /* not found */
784 /* find minimal match */ 855 /* find minimal match */
785 // ash: yet another failure in trying to achieve "we don't die on OOM"
786 tmp1 = xstrdup(matches[0]); 856 tmp1 = xstrdup(matches[0]);
787 for (tmp = tmp1; *tmp; tmp++) 857 for (tmp = tmp1; *tmp; tmp++)
788 for (len_found = 1; len_found < num_matches; len_found++) 858 for (len_found = 1; len_found < num_matches; len_found++)
@@ -811,7 +881,7 @@ static void input_tab(int *lastWasTab)
811 /* have space to placed match? */ 881 /* have space to placed match? */
812 if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) { 882 if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) {
813 /* before word for match */ 883 /* before word for match */
814 command_ps[cursor - recalc_pos] = 0; 884 command_ps[cursor - recalc_pos] = '\0';
815 /* save tail line */ 885 /* save tail line */
816 strcpy(matchBuf, command_ps + cursor); 886 strcpy(matchBuf, command_ps + cursor);
817 /* add match */ 887 /* add match */
@@ -828,6 +898,7 @@ static void input_tab(int *lastWasTab)
828 redraw(cmdedit_y, command_len - recalc_pos); 898 redraw(cmdedit_y, command_len - recalc_pos);
829 } 899 }
830 free(tmp); 900 free(tmp);
901#undef matchBuf
831 } else { 902 } else {
832 /* Ok -- the last char was a TAB. Since they 903 /* Ok -- the last char was a TAB. Since they
833 * just hit TAB again, print a list of all the 904 * just hit TAB again, print a list of all the
@@ -843,8 +914,6 @@ static void input_tab(int *lastWasTab)
843 } 914 }
844} 915}
845 916
846#else
847#define input_tab(a) ((void)0)
848#endif /* FEATURE_COMMAND_TAB_COMPLETION */ 917#endif /* FEATURE_COMMAND_TAB_COMPLETION */
849 918
850 919
@@ -1079,14 +1148,14 @@ vi_back_motion(char *command)
1079 */ 1148 */
1080 1149
1081#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT 1150#if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
1082static void parse_prompt(const char *prmt_ptr) 1151static void parse_and_put_prompt(const char *prmt_ptr)
1083{ 1152{
1084 cmdedit_prompt = prmt_ptr; 1153 cmdedit_prompt = prmt_ptr;
1085 cmdedit_prmt_len = strlen(prmt_ptr); 1154 cmdedit_prmt_len = strlen(prmt_ptr);
1086 put_prompt(); 1155 put_prompt();
1087} 1156}
1088#else 1157#else
1089static void parse_prompt(const char *prmt_ptr) 1158static void parse_and_put_prompt(const char *prmt_ptr)
1090{ 1159{
1091 int prmt_len = 0; 1160 int prmt_len = 0;
1092 size_t cur_prmt_len = 0; 1161 size_t cur_prmt_len = 0;
@@ -1114,7 +1183,7 @@ static void parse_prompt(const char *prmt_ptr)
1114 1183
1115 c = bb_process_escape_sequence(&prmt_ptr); 1184 c = bb_process_escape_sequence(&prmt_ptr);
1116 if (prmt_ptr == cp) { 1185 if (prmt_ptr == cp) {
1117 if (*cp == 0) 1186 if (*cp == '\0')
1118 break; 1187 break;
1119 c = *prmt_ptr++; 1188 c = *prmt_ptr++;
1120 switch (c) { 1189 switch (c) {
@@ -1147,7 +1216,7 @@ static void parse_prompt(const char *prmt_ptr)
1147 if (l != 0 1216 if (l != 0
1148 && strncmp(home_pwd_buf, pbuf, l) == 0 1217 && strncmp(home_pwd_buf, pbuf, l) == 0
1149 && (pbuf[l]=='/' || pbuf[l]=='\0') 1218 && (pbuf[l]=='/' || pbuf[l]=='\0')
1150 && strlen(pwd_buf+l)<PATH_MAX 1219 && strlen(pwd_buf+l) < PATH_MAX
1151 ) { 1220 ) {
1152 pbuf = buf2; 1221 pbuf = buf2;
1153 *pbuf = '~'; 1222 *pbuf = '~';
@@ -1188,7 +1257,7 @@ static void parse_prompt(const char *prmt_ptr)
1188 break; 1257 break;
1189 case '[': case ']': 1258 case '[': case ']':
1190 if (c == flg_not_length) { 1259 if (c == flg_not_length) {
1191 flg_not_length = flg_not_length == '[' ? ']' : '['; 1260 flg_not_length = (flg_not_length == '[' ? ']' : '[');
1192 continue; 1261 continue;
1193 } 1262 }
1194 break; 1263 break;
@@ -1210,11 +1279,6 @@ static void parse_prompt(const char *prmt_ptr)
1210} 1279}
1211#endif 1280#endif
1212 1281
1213#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
1214#define getTermSettings(fd, argp) tcgetattr(fd, argp);
1215
1216static sighandler_t previous_SIGWINCH_handler;
1217
1218static void cmdedit_setwidth(unsigned w, int redraw_flg) 1282static void cmdedit_setwidth(unsigned w, int redraw_flg)
1219{ 1283{
1220 cmdedit_termw = w; 1284 cmdedit_termw = w;
@@ -1261,7 +1325,9 @@ static void win_changed(int nsig)
1261 */ 1325 */
1262int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) 1326int read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
1263{ 1327{
1264 int lastWasTab = FALSE; 1328#if ENABLE_FEATURE_TAB_COMPLETION
1329 smallint lastWasTab = FALSE;
1330#endif
1265 unsigned int ic; 1331 unsigned int ic;
1266 unsigned char c; 1332 unsigned char c;
1267 smallint break_out = 0; 1333 smallint break_out = 0;
@@ -1269,14 +1335,22 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1269 smallint vi_cmdmode = 0; 1335 smallint vi_cmdmode = 0;
1270 smalluint prevc; 1336 smalluint prevc;
1271#endif 1337#endif
1338 struct termios initial_settings;
1339 struct termios new_settings;
1272 1340
1273 getTermSettings(0, (void *) &initial_settings); 1341 INIT_S();
1274 /* Happens when e.g. stty -echo was run before */ 1342
1275 if (!(initial_settings.c_lflag & ECHO)) { 1343 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
1276 parse_prompt(prompt); 1344 || !(initial_settings.c_lflag & ECHO)
1345 ) {
1346 /* Happens when e.g. stty -echo was run before */
1347 int len;
1348 parse_and_put_prompt(prompt);
1277 fflush(stdout); 1349 fflush(stdout);
1278 fgets(command, maxsize, stdin); 1350 fgets(command, maxsize, stdin);
1279 return strlen(command); 1351 len = strlen(command);
1352 DEINIT_S();
1353 return len;
1280 } 1354 }
1281 1355
1282// FIXME: audit & improve this 1356// FIXME: audit & improve this
@@ -1296,7 +1370,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1296 command_ps = command; 1370 command_ps = command;
1297 command[0] = '\0'; 1371 command[0] = '\0';
1298 1372
1299 memcpy(&new_settings, &initial_settings, sizeof(new_settings)); 1373 new_settings = initial_settings;
1300 new_settings.c_lflag &= ~ICANON; /* unbuffered input */ 1374 new_settings.c_lflag &= ~ICANON; /* unbuffered input */
1301 /* Turn off echoing and CTRL-C, so we can trap it */ 1375 /* Turn off echoing and CTRL-C, so we can trap it */
1302 new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); 1376 new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
@@ -1308,7 +1382,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1308#define _POSIX_VDISABLE '\0' 1382#define _POSIX_VDISABLE '\0'
1309#endif 1383#endif
1310 new_settings.c_cc[VINTR] = _POSIX_VDISABLE; 1384 new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
1311 setTermSettings(0, (void *) &new_settings); 1385 tcsetattr(STDIN_FILENO, TCSANOW, &new_settings);
1312 1386
1313 /* Now initialize things */ 1387 /* Now initialize things */
1314 previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); 1388 previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
@@ -1319,11 +1393,6 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1319 1393
1320 entry = getpwuid(geteuid()); 1394 entry = getpwuid(geteuid());
1321 if (entry) { 1395 if (entry) {
1322 /* If we enter read_line_input for the Nth time,
1323 * they may be already allocated! Need to free. */
1324 free(user_buf);
1325 if (home_pwd_buf != null_str)
1326 free(home_pwd_buf);
1327 user_buf = xstrdup(entry->pw_name); 1396 user_buf = xstrdup(entry->pw_name);
1328 home_pwd_buf = xstrdup(entry->pw_dir); 1397 home_pwd_buf = xstrdup(entry->pw_dir);
1329 /* They are not freed on exit (too small to bother) */ 1398 /* They are not freed on exit (too small to bother) */
@@ -1331,12 +1400,12 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1331 } 1400 }
1332#endif 1401#endif
1333 /* Print out the command prompt */ 1402 /* Print out the command prompt */
1334 parse_prompt(prompt); 1403 parse_and_put_prompt(prompt);
1335 1404
1336 while (1) { 1405 while (1) {
1337 fflush(stdout); 1406 fflush(stdout);
1338 1407
1339 if (safe_read(0, &c, 1) < 1) { 1408 if (safe_read(STDIN_FILENO, &c, 1) < 1) {
1340 /* if we can't read input then exit */ 1409 /* if we can't read input then exit */
1341 goto prepare_to_die; 1410 goto prepare_to_die;
1342 } 1411 }
@@ -1411,9 +1480,11 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1411 input_backspace(); 1480 input_backspace();
1412 break; 1481 break;
1413 1482
1483#if ENABLE_FEATURE_TAB_COMPLETION
1414 case '\t': 1484 case '\t':
1415 input_tab(&lastWasTab); 1485 input_tab(&lastWasTab);
1416 break; 1486 break;
1487#endif
1417 1488
1418#if ENABLE_FEATURE_EDITING_FANCY_KEYS 1489#if ENABLE_FEATURE_EDITING_FANCY_KEYS
1419 case CTRL('K'): 1490 case CTRL('K'):
@@ -1526,7 +1597,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1526 int nc, sc; 1597 int nc, sc;
1527 sc = cursor; 1598 sc = cursor;
1528 prevc = ic; 1599 prevc = ic;
1529 if (safe_read(0, &c, 1) < 1) 1600 if (safe_read(STDIN_FILENO, &c, 1) < 1)
1530 goto prepare_to_die; 1601 goto prepare_to_die;
1531 if (c == (prevc & 0xff)) { 1602 if (c == (prevc & 0xff)) {
1532 /* "cc", "dd" */ 1603 /* "cc", "dd" */
@@ -1587,7 +1658,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1587 put(); 1658 put();
1588 break; 1659 break;
1589 case 'r'|vbit: 1660 case 'r'|vbit:
1590 if (safe_read(0, &c, 1) < 1) 1661 if (safe_read(STDIN_FILENO, &c, 1) < 1)
1591 goto prepare_to_die; 1662 goto prepare_to_die;
1592 if (c == 0) 1663 if (c == 0)
1593 beep(); 1664 beep();
@@ -1610,19 +1681,19 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1610 } 1681 }
1611#endif 1682#endif
1612 /* escape sequence follows */ 1683 /* escape sequence follows */
1613 if (safe_read(0, &c, 1) < 1) 1684 if (safe_read(STDIN_FILENO, &c, 1) < 1)
1614 goto prepare_to_die; 1685 goto prepare_to_die;
1615 /* different vt100 emulations */ 1686 /* different vt100 emulations */
1616 if (c == '[' || c == 'O') { 1687 if (c == '[' || c == 'O') {
1617 vi_case('['|vbit:) 1688 vi_case('['|vbit:)
1618 vi_case('O'|vbit:) 1689 vi_case('O'|vbit:)
1619 if (safe_read(0, &c, 1) < 1) 1690 if (safe_read(STDIN_FILENO, &c, 1) < 1)
1620 goto prepare_to_die; 1691 goto prepare_to_die;
1621 } 1692 }
1622 if (c >= '1' && c <= '9') { 1693 if (c >= '1' && c <= '9') {
1623 unsigned char dummy; 1694 unsigned char dummy;
1624 1695
1625 if (safe_read(0, &dummy, 1) < 1) 1696 if (safe_read(STDIN_FILENO, &dummy, 1) < 1)
1626 goto prepare_to_die; 1697 goto prepare_to_die;
1627 if (dummy != '~') 1698 if (dummy != '~')
1628 c = '\0'; 1699 c = '\0';
@@ -1687,7 +1758,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1687#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 1758#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
1688 /* Control-V -- Add non-printable symbol */ 1759 /* Control-V -- Add non-printable symbol */
1689 if (c == CTRL('V')) { 1760 if (c == CTRL('V')) {
1690 if (safe_read(0, &c, 1) < 1) 1761 if (safe_read(STDIN_FILENO, &c, 1) < 1)
1691 goto prepare_to_die; 1762 goto prepare_to_die;
1692 if (c == 0) { 1763 if (c == 0) {
1693 beep(); 1764 beep();
@@ -1727,8 +1798,10 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1727 if (break_out) /* Enter is the command terminator, no more input. */ 1798 if (break_out) /* Enter is the command terminator, no more input. */
1728 break; 1799 break;
1729 1800
1801#if ENABLE_FEATURE_TAB_COMPLETION
1730 if (c != '\t') 1802 if (c != '\t')
1731 lastWasTab = FALSE; 1803 lastWasTab = FALSE;
1804#endif
1732 } 1805 }
1733 1806
1734 if (command_len > 0) 1807 if (command_len > 0)
@@ -1739,18 +1812,18 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1739 command[command_len] = '\0'; 1812 command[command_len] = '\0';
1740 } 1813 }
1741 1814
1742#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_TAB_COMPLETION 1815#if ENABLE_FEATURE_TAB_COMPLETION
1743 free_tab_completion_data(); 1816 free_tab_completion_data();
1744#endif 1817#endif
1745 1818
1746#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
1747 free((char*)cmdedit_prompt);
1748#endif
1749 /* restore initial_settings */ 1819 /* restore initial_settings */
1750 setTermSettings(STDIN_FILENO, (void *) &initial_settings); 1820 tcsetattr(STDIN_FILENO, TCSANOW, &initial_settings);
1751 /* restore SIGWINCH handler */ 1821 /* restore SIGWINCH handler */
1752 signal(SIGWINCH, previous_SIGWINCH_handler); 1822 signal(SIGWINCH, previous_SIGWINCH_handler);
1753 fflush(stdout); 1823 fflush(stdout);
1824
1825 DEINIT_S();
1826
1754 return command_len; 1827 return command_len;
1755} 1828}
1756 1829