lineedit.c 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Termios command line History and Editing.
  4. *
  5. * Copyright (c) 1986-2003 may safely be consumed by a BSD or GPL license.
  6. * Written by: Vladimir Oleynik <dzo@simtreas.ru>
  7. *
  8. * Used ideas:
  9. * Adam Rogoyski <rogoyski@cs.utexas.edu>
  10. * Dave Cinege <dcinege@psychosis.com>
  11. * Jakub Jelinek (c) 1995
  12. * Erik Andersen <andersen@codepoet.org> (Majorly adjusted for busybox)
  13. *
  14. * This code is 'as is' with no warranty.
  15. */
  16. /*
  17. * Usage and known bugs:
  18. * Terminal key codes are not extensive, more needs to be added.
  19. * This version was created on Debian GNU/Linux 2.x.
  20. * Delete, Backspace, Home, End, and the arrow keys were tested
  21. * to work in an Xterm and console. Ctrl-A also works as Home.
  22. * Ctrl-E also works as End.
  23. *
  24. * The following readline-like commands are not implemented:
  25. * ESC-b -- Move back one word
  26. * ESC-f -- Move forward one word
  27. * ESC-d -- Delete forward one word
  28. * CTL-t -- Transpose two characters
  29. *
  30. * lineedit does not know that the terminal escape sequences do not
  31. * take up space on the screen. The redisplay code assumes, unless
  32. * told otherwise, that each character in the prompt is a printable
  33. * character that takes up one character position on the screen.
  34. * You need to tell lineedit that some sequences of characters
  35. * in the prompt take up no screen space. Compatibly with readline,
  36. * use the \[ escape to begin a sequence of non-printing characters,
  37. * and the \] escape to signal the end of such a sequence. Example:
  38. *
  39. * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
  40. */
  41. #include "libbb.h"
  42. #include "unicode.h"
  43. /* FIXME: obsolete CONFIG item? */
  44. #define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0
  45. #ifdef TEST
  46. # define ENABLE_FEATURE_EDITING 0
  47. # define ENABLE_FEATURE_TAB_COMPLETION 0
  48. # define ENABLE_FEATURE_USERNAME_COMPLETION 0
  49. # define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0
  50. #endif
  51. /* Entire file (except TESTing part) sits inside this #if */
  52. #if ENABLE_FEATURE_EDITING
  53. #define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \
  54. (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT)
  55. #define IF_FEATURE_GETUSERNAME_AND_HOMEDIR(...)
  56. #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  57. #undef IF_FEATURE_GETUSERNAME_AND_HOMEDIR
  58. #define IF_FEATURE_GETUSERNAME_AND_HOMEDIR(...) __VA_ARGS__
  59. #endif
  60. #undef CHAR_T
  61. #if ENABLE_UNICODE_SUPPORT
  62. # define BB_NUL ((wchar_t)0)
  63. # define CHAR_T wchar_t
  64. static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); }
  65. # if ENABLE_FEATURE_EDITING_VI
  66. static bool BB_isalnum(CHAR_T c) { return ((unsigned)c < 256 && isalnum(c)); }
  67. # endif
  68. static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); }
  69. # undef isspace
  70. # undef isalnum
  71. # undef ispunct
  72. # undef isprint
  73. # define isspace isspace_must_not_be_used
  74. # define isalnum isalnum_must_not_be_used
  75. # define ispunct ispunct_must_not_be_used
  76. # define isprint isprint_must_not_be_used
  77. #else
  78. # define BB_NUL '\0'
  79. # define CHAR_T char
  80. # define BB_isspace(c) isspace(c)
  81. # define BB_isalnum(c) isalnum(c)
  82. # define BB_ispunct(c) ispunct(c)
  83. #endif
  84. # if ENABLE_UNICODE_PRESERVE_BROKEN
  85. # define unicode_mark_inv_wchar(wc) ((wc) | 0x20000000)
  86. # define unicode_is_inv_wchar(wc) ((wc) & 0x20000000)
  87. # else
  88. # define unicode_is_inv_wchar(wc) 0
  89. # endif
  90. enum {
  91. /* We use int16_t for positions, need to limit line len */
  92. MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0
  93. ? CONFIG_FEATURE_EDITING_MAX_LEN
  94. : 0x7ff0
  95. };
  96. #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  97. static const char null_str[] ALIGN1 = "";
  98. #endif
  99. /* We try to minimize both static and stack usage. */
  100. struct lineedit_statics {
  101. line_input_t *state;
  102. volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
  103. sighandler_t previous_SIGWINCH_handler;
  104. unsigned cmdedit_x; /* real x (col) terminal position */
  105. unsigned cmdedit_y; /* pseudoreal y (row) terminal position */
  106. unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */
  107. unsigned cursor;
  108. int command_len; /* must be signed */
  109. /* signed maxsize: we want x in "if (x > S.maxsize)"
  110. * to _not_ be promoted to unsigned */
  111. int maxsize;
  112. CHAR_T *command_ps;
  113. const char *cmdedit_prompt;
  114. #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
  115. int num_ok_lines; /* = 1; */
  116. #endif
  117. #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  118. char *user_buf;
  119. char *home_pwd_buf; /* = (char*)null_str; */
  120. #endif
  121. #if ENABLE_FEATURE_TAB_COMPLETION
  122. char **matches;
  123. unsigned num_matches;
  124. #endif
  125. #if ENABLE_FEATURE_EDITING_VI
  126. #define DELBUFSIZ 128
  127. CHAR_T *delptr;
  128. smallint newdelflag; /* whether delbuf should be reused yet */
  129. CHAR_T delbuf[DELBUFSIZ]; /* a place to store deleted characters */
  130. #endif
  131. #if ENABLE_FEATURE_EDITING_ASK_TERMINAL
  132. smallint sent_ESC_br6n;
  133. #endif
  134. /* Formerly these were big buffers on stack: */
  135. #if ENABLE_FEATURE_TAB_COMPLETION
  136. char exe_n_cwd_tab_completion__dirbuf[MAX_LINELEN];
  137. char input_tab__matchBuf[MAX_LINELEN];
  138. int16_t find_match__int_buf[MAX_LINELEN + 1]; /* need to have 9 bits at least */
  139. int16_t find_match__pos_buf[MAX_LINELEN + 1];
  140. #endif
  141. };
  142. /* See lineedit_ptr_hack.c */
  143. extern struct lineedit_statics *const lineedit_ptr_to_statics;
  144. #define S (*lineedit_ptr_to_statics)
  145. #define state (S.state )
  146. #define cmdedit_termw (S.cmdedit_termw )
  147. #define previous_SIGWINCH_handler (S.previous_SIGWINCH_handler)
  148. #define cmdedit_x (S.cmdedit_x )
  149. #define cmdedit_y (S.cmdedit_y )
  150. #define cmdedit_prmt_len (S.cmdedit_prmt_len)
  151. #define cursor (S.cursor )
  152. #define command_len (S.command_len )
  153. #define command_ps (S.command_ps )
  154. #define cmdedit_prompt (S.cmdedit_prompt )
  155. #define num_ok_lines (S.num_ok_lines )
  156. #define user_buf (S.user_buf )
  157. #define home_pwd_buf (S.home_pwd_buf )
  158. #define matches (S.matches )
  159. #define num_matches (S.num_matches )
  160. #define delptr (S.delptr )
  161. #define newdelflag (S.newdelflag )
  162. #define delbuf (S.delbuf )
  163. #define INIT_S() do { \
  164. (*(struct lineedit_statics**)&lineedit_ptr_to_statics) = xzalloc(sizeof(S)); \
  165. barrier(); \
  166. cmdedit_termw = 80; \
  167. IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines = 1;) \
  168. IF_FEATURE_GETUSERNAME_AND_HOMEDIR(home_pwd_buf = (char*)null_str;) \
  169. } while (0)
  170. static void deinit_S(void)
  171. {
  172. #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
  173. /* This one is allocated only if FANCY_PROMPT is on
  174. * (otherwise it points to verbatim prompt (NOT malloced) */
  175. free((char*)cmdedit_prompt);
  176. #endif
  177. #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  178. free(user_buf);
  179. if (home_pwd_buf != null_str)
  180. free(home_pwd_buf);
  181. #endif
  182. free(lineedit_ptr_to_statics);
  183. }
  184. #define DEINIT_S() deinit_S()
  185. #if ENABLE_UNICODE_SUPPORT
  186. static size_t load_string(const char *src, int maxsize)
  187. {
  188. ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
  189. if (len < 0)
  190. len = 0;
  191. command_ps[len] = 0;
  192. return len;
  193. }
  194. static unsigned save_string(char *dst, unsigned maxsize)
  195. {
  196. #if !ENABLE_UNICODE_PRESERVE_BROKEN
  197. ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
  198. if (len < 0)
  199. len = 0;
  200. dst[len] = '\0';
  201. return len;
  202. #else
  203. unsigned dstpos = 0;
  204. unsigned srcpos = 0;
  205. maxsize--;
  206. while (dstpos < maxsize) {
  207. wchar_t wc;
  208. int n = srcpos;
  209. while ((wc = command_ps[srcpos]) != 0
  210. && !unicode_is_inv_wchar(wc)
  211. ) {
  212. srcpos++;
  213. }
  214. command_ps[srcpos] = 0;
  215. n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
  216. if (n < 0) /* should not happen */
  217. break;
  218. dstpos += n;
  219. if (wc == 0) /* usually is */
  220. break;
  221. /* We do have invalid byte here! */
  222. command_ps[srcpos] = wc; /* restore it */
  223. srcpos++;
  224. if (dstpos == maxsize)
  225. break;
  226. dst[dstpos++] = (char) wc;
  227. }
  228. dst[dstpos] = '\0';
  229. return dstpos;
  230. #endif
  231. }
  232. /* I thought just fputwc(c, stdout) would work. But no... */
  233. static void BB_PUTCHAR(wchar_t c)
  234. {
  235. char buf[MB_CUR_MAX + 1];
  236. mbstate_t mbst = { 0 };
  237. ssize_t len;
  238. if (unicode_is_inv_wchar(c))
  239. c = CONFIG_SUBST_WCHAR;
  240. len = wcrtomb(buf, c, &mbst);
  241. if (len > 0) {
  242. buf[len] = '\0';
  243. fputs(buf, stdout);
  244. }
  245. }
  246. #else
  247. static size_t load_string(const char *src, int maxsize)
  248. {
  249. safe_strncpy(command_ps, src, maxsize);
  250. return strlen(command_ps);
  251. }
  252. # if ENABLE_FEATURE_TAB_COMPLETION
  253. static void save_string(char *dst, unsigned maxsize)
  254. {
  255. safe_strncpy(dst, command_ps, maxsize);
  256. }
  257. # endif
  258. # define BB_PUTCHAR(c) bb_putchar(c)
  259. #endif
  260. /* Put 'command_ps[cursor]', cursor++.
  261. * Advance cursor on screen. If we reached right margin, scroll text up
  262. * and remove terminal margin effect by printing 'next_char' */
  263. #define HACK_FOR_WRONG_WIDTH 1
  264. #if HACK_FOR_WRONG_WIDTH
  265. static void cmdedit_set_out_char(void)
  266. #define cmdedit_set_out_char(next_char) cmdedit_set_out_char()
  267. #else
  268. static void cmdedit_set_out_char(int next_char)
  269. #endif
  270. {
  271. CHAR_T c = command_ps[cursor];
  272. if (c == BB_NUL) {
  273. /* erase character after end of input string */
  274. c = ' ';
  275. }
  276. #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
  277. /* Display non-printable characters in reverse */
  278. if (!BB_isprint(c)) {
  279. if (c >= 128)
  280. c -= 128;
  281. if (c < ' ')
  282. c += '@';
  283. if (c == 127)
  284. c = '?';
  285. printf("\033[7m%c\033[0m", c);
  286. } else
  287. #endif
  288. {
  289. BB_PUTCHAR(c);
  290. }
  291. if (++cmdedit_x >= cmdedit_termw) {
  292. /* terminal is scrolled down */
  293. cmdedit_y++;
  294. cmdedit_x = 0;
  295. #if HACK_FOR_WRONG_WIDTH
  296. /* This works better if our idea of term width is wrong
  297. * and it is actually wider (often happens on serial lines).
  298. * Printing CR,LF *forces* cursor to next line.
  299. * OTOH if terminal width is correct AND terminal does NOT
  300. * have automargin (IOW: it is moving cursor to next line
  301. * by itself (which is wrong for VT-10x terminals)),
  302. * this will break things: there will be one extra empty line */
  303. puts("\r"); /* + implicit '\n' */
  304. #else
  305. /* Works ok only if cmdedit_termw is correct */
  306. /* destroy "(auto)margin" */
  307. bb_putchar(next_char);
  308. bb_putchar('\b');
  309. #endif
  310. }
  311. // Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?)
  312. cursor++;
  313. }
  314. /* Move to end of line (by printing all chars till the end) */
  315. static void input_end(void)
  316. {
  317. while (cursor < command_len)
  318. cmdedit_set_out_char(' ');
  319. }
  320. /* Go to the next line */
  321. static void goto_new_line(void)
  322. {
  323. input_end();
  324. if (cmdedit_x)
  325. bb_putchar('\n');
  326. }
  327. static void out1str(const char *s)
  328. {
  329. if (s)
  330. fputs(s, stdout);
  331. }
  332. static void beep(void)
  333. {
  334. bb_putchar('\007');
  335. }
  336. /* Move back one character */
  337. /* (optimized for slow terminals) */
  338. static void input_backward(unsigned num)
  339. {
  340. int count_y;
  341. if (num > cursor)
  342. num = cursor;
  343. if (!num)
  344. return;
  345. cursor -= num;
  346. if (cmdedit_x >= num) {
  347. cmdedit_x -= num;
  348. if (num <= 4) {
  349. /* This is longer by 5 bytes on x86.
  350. * Also gets miscompiled for ARM users
  351. * (busybox.net/bugs/view.php?id=2274).
  352. * printf(("\b\b\b\b" + 4) - num);
  353. * return;
  354. */
  355. do {
  356. bb_putchar('\b');
  357. } while (--num);
  358. return;
  359. }
  360. printf("\033[%uD", num);
  361. return;
  362. }
  363. /* Need to go one or more lines up */
  364. num -= cmdedit_x;
  365. {
  366. unsigned w = cmdedit_termw; /* volatile var */
  367. count_y = 1 + (num / w);
  368. cmdedit_y -= count_y;
  369. cmdedit_x = w * count_y - num;
  370. }
  371. /* go to 1st column; go up; go to correct column */
  372. printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x);
  373. }
  374. static void put_prompt(void)
  375. {
  376. unsigned w;
  377. out1str(cmdedit_prompt);
  378. fflush_all();
  379. cursor = 0;
  380. w = cmdedit_termw; /* read volatile var once */
  381. cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
  382. cmdedit_x = cmdedit_prmt_len % w;
  383. }
  384. /* draw prompt, editor line, and clear tail */
  385. static void redraw(int y, int back_cursor)
  386. {
  387. if (y > 0) /* up to start y */
  388. printf("\033[%uA", y);
  389. bb_putchar('\r');
  390. put_prompt();
  391. input_end(); /* rewrite */
  392. printf("\033[J"); /* erase after cursor */
  393. input_backward(back_cursor);
  394. }
  395. /* Delete the char in front of the cursor, optionally saving it
  396. * for later putback */
  397. #if !ENABLE_FEATURE_EDITING_VI
  398. static void input_delete(void)
  399. #define input_delete(save) input_delete()
  400. #else
  401. static void input_delete(int save)
  402. #endif
  403. {
  404. int j = cursor;
  405. if (j == (int)command_len)
  406. return;
  407. #if ENABLE_FEATURE_EDITING_VI
  408. if (save) {
  409. if (newdelflag) {
  410. delptr = delbuf;
  411. newdelflag = 0;
  412. }
  413. if ((delptr - delbuf) < DELBUFSIZ)
  414. *delptr++ = command_ps[j];
  415. }
  416. #endif
  417. memmove(command_ps + j, command_ps + j + 1,
  418. /* (command_len + 1 [because of NUL]) - (j + 1)
  419. * simplified into (command_len - j) */
  420. (command_len - j) * sizeof(command_ps[0]));
  421. command_len--;
  422. input_end(); /* rewrite new line */
  423. cmdedit_set_out_char(' '); /* erase char */
  424. input_backward(cursor - j); /* back to old pos cursor */
  425. }
  426. #if ENABLE_FEATURE_EDITING_VI
  427. static void put(void)
  428. {
  429. int ocursor;
  430. int j = delptr - delbuf;
  431. if (j == 0)
  432. return;
  433. ocursor = cursor;
  434. /* open hole and then fill it */
  435. memmove(command_ps + cursor + j, command_ps + cursor,
  436. (command_len - cursor + 1) * sizeof(command_ps[0]));
  437. memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0]));
  438. command_len += j;
  439. input_end(); /* rewrite new line */
  440. input_backward(cursor - ocursor - j + 1); /* at end of new text */
  441. }
  442. #endif
  443. /* Delete the char in back of the cursor */
  444. static void input_backspace(void)
  445. {
  446. if (cursor > 0) {
  447. input_backward(1);
  448. input_delete(0);
  449. }
  450. }
  451. /* Move forward one character */
  452. static void input_forward(void)
  453. {
  454. if (cursor < command_len)
  455. cmdedit_set_out_char(command_ps[cursor + 1]);
  456. }
  457. #if ENABLE_FEATURE_TAB_COMPLETION
  458. static void free_tab_completion_data(void)
  459. {
  460. if (matches) {
  461. while (num_matches)
  462. free(matches[--num_matches]);
  463. free(matches);
  464. matches = NULL;
  465. }
  466. }
  467. static void add_match(char *matched)
  468. {
  469. matches = xrealloc_vector(matches, 4, num_matches);
  470. matches[num_matches] = matched;
  471. num_matches++;
  472. }
  473. #if ENABLE_FEATURE_USERNAME_COMPLETION
  474. static void username_tab_completion(char *ud, char *with_shash_flg)
  475. {
  476. struct passwd *entry;
  477. int userlen;
  478. ud++; /* ~user/... to user/... */
  479. userlen = strlen(ud);
  480. if (with_shash_flg) { /* "~/..." or "~user/..." */
  481. char *sav_ud = ud - 1;
  482. char *home = NULL;
  483. if (*ud == '/') { /* "~/..." */
  484. home = home_pwd_buf;
  485. } else {
  486. /* "~user/..." */
  487. char *temp;
  488. temp = strchr(ud, '/');
  489. *temp = '\0'; /* ~user\0 */
  490. entry = getpwnam(ud);
  491. *temp = '/'; /* restore ~user/... */
  492. ud = temp;
  493. if (entry)
  494. home = entry->pw_dir;
  495. }
  496. if (home) {
  497. if ((userlen + strlen(home) + 1) < MAX_LINELEN) {
  498. /* /home/user/... */
  499. sprintf(sav_ud, "%s%s", home, ud);
  500. }
  501. }
  502. } else {
  503. /* "~[^/]*" */
  504. /* Using _r function to avoid pulling in static buffers */
  505. char line_buff[256];
  506. struct passwd pwd;
  507. struct passwd *result;
  508. setpwent();
  509. while (!getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) {
  510. /* Null usernames should result in all users as possible completions. */
  511. if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) {
  512. add_match(xasprintf("~%s/", pwd.pw_name));
  513. }
  514. }
  515. endpwent();
  516. }
  517. }
  518. #endif /* FEATURE_COMMAND_USERNAME_COMPLETION */
  519. enum {
  520. FIND_EXE_ONLY = 0,
  521. FIND_DIR_ONLY = 1,
  522. FIND_FILE_ONLY = 2,
  523. };
  524. static int path_parse(char ***p, int flags)
  525. {
  526. int npth;
  527. const char *pth;
  528. char *tmp;
  529. char **res;
  530. /* if not setenv PATH variable, to search cur dir "." */
  531. if (flags != FIND_EXE_ONLY)
  532. return 1;
  533. if (state->flags & WITH_PATH_LOOKUP)
  534. pth = state->path_lookup;
  535. else
  536. pth = getenv("PATH");
  537. /* PATH=<empty> or PATH=:<empty> */
  538. if (!pth || !pth[0] || LONE_CHAR(pth, ':'))
  539. return 1;
  540. tmp = (char*)pth;
  541. npth = 1; /* path component count */
  542. while (1) {
  543. tmp = strchr(tmp, ':');
  544. if (!tmp)
  545. break;
  546. if (*++tmp == '\0')
  547. break; /* :<empty> */
  548. npth++;
  549. }
  550. res = xmalloc(npth * sizeof(char*));
  551. res[0] = tmp = xstrdup(pth);
  552. npth = 1;
  553. while (1) {
  554. tmp = strchr(tmp, ':');
  555. if (!tmp)
  556. break;
  557. *tmp++ = '\0'; /* ':' -> '\0' */
  558. if (*tmp == '\0')
  559. break; /* :<empty> */
  560. res[npth++] = tmp;
  561. }
  562. *p = res;
  563. return npth;
  564. }
  565. static void exe_n_cwd_tab_completion(char *command, int type)
  566. {
  567. DIR *dir;
  568. struct dirent *next;
  569. struct stat st;
  570. char *path1[1];
  571. char **paths = path1;
  572. int npaths;
  573. int i;
  574. char *found;
  575. char *pfind = strrchr(command, '/');
  576. /* char dirbuf[MAX_LINELEN]; */
  577. #define dirbuf (S.exe_n_cwd_tab_completion__dirbuf)
  578. npaths = 1;
  579. path1[0] = (char*)".";
  580. if (pfind == NULL) {
  581. /* no dir, if flags==EXE_ONLY - get paths, else "." */
  582. npaths = path_parse(&paths, type);
  583. pfind = command;
  584. } else {
  585. /* dirbuf = ".../.../.../" */
  586. safe_strncpy(dirbuf, command, (pfind - command) + 2);
  587. #if ENABLE_FEATURE_USERNAME_COMPLETION
  588. if (dirbuf[0] == '~') /* ~/... or ~user/... */
  589. username_tab_completion(dirbuf, dirbuf);
  590. #endif
  591. paths[0] = dirbuf;
  592. /* point to 'l' in "..../last_component" */
  593. pfind++;
  594. }
  595. for (i = 0; i < npaths; i++) {
  596. dir = opendir(paths[i]);
  597. if (!dir)
  598. continue; /* don't print an error */
  599. while ((next = readdir(dir)) != NULL) {
  600. int len1;
  601. const char *str_found = next->d_name;
  602. /* matched? */
  603. if (strncmp(str_found, pfind, strlen(pfind)))
  604. continue;
  605. /* not see .name without .match */
  606. if (*str_found == '.' && *pfind == '\0') {
  607. if (NOT_LONE_CHAR(paths[i], '/') || str_found[1])
  608. continue;
  609. str_found = ""; /* only "/" */
  610. }
  611. found = concat_path_file(paths[i], str_found);
  612. /* hmm, remove in progress? */
  613. /* NB: stat() first so that we see is it a directory;
  614. * but if that fails, use lstat() so that
  615. * we still match dangling links */
  616. if (stat(found, &st) && lstat(found, &st))
  617. goto cont;
  618. /* find with dirs? */
  619. if (paths[i] != dirbuf)
  620. strcpy(found, next->d_name); /* only name */
  621. len1 = strlen(found);
  622. found = xrealloc(found, len1 + 2);
  623. found[len1] = '\0';
  624. found[len1+1] = '\0';
  625. if (S_ISDIR(st.st_mode)) {
  626. /* name is a directory */
  627. if (found[len1-1] != '/') {
  628. found[len1] = '/';
  629. }
  630. } else {
  631. /* not put found file if search only dirs for cd */
  632. if (type == FIND_DIR_ONLY)
  633. goto cont;
  634. }
  635. /* Add it to the list */
  636. add_match(found);
  637. continue;
  638. cont:
  639. free(found);
  640. }
  641. closedir(dir);
  642. }
  643. if (paths != path1) {
  644. free(paths[0]); /* allocated memory is only in first member */
  645. free(paths);
  646. }
  647. #undef dirbuf
  648. }
  649. /* QUOT is used on elements of int_buf[], which are bytes,
  650. * not Unicode chars. Therefore it works correctly even in Unicode mode.
  651. */
  652. #define QUOT (UCHAR_MAX+1)
  653. #define int_buf (S.find_match__int_buf)
  654. #define pos_buf (S.find_match__pos_buf)
  655. /* is must be <= in */
  656. static void collapse_pos(int is, int in)
  657. {
  658. memmove(int_buf+is, int_buf+in, (MAX_LINELEN+1-in)*sizeof(int_buf[0]));
  659. memmove(pos_buf+is, pos_buf+in, (MAX_LINELEN+1-in)*sizeof(pos_buf[0]));
  660. }
  661. static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
  662. {
  663. int i, j;
  664. int command_mode;
  665. int c, c2;
  666. /* Were local, but it uses too much stack */
  667. /* int16_t int_buf[MAX_LINELEN + 1]; */
  668. /* int16_t pos_buf[MAX_LINELEN + 1]; */
  669. /* set to integer dimension characters and own positions */
  670. for (i = 0;; i++) {
  671. int_buf[i] = (unsigned char)matchBuf[i];
  672. if (int_buf[i] == 0) {
  673. pos_buf[i] = -1; /* end-fo-line indicator */
  674. break;
  675. }
  676. pos_buf[i] = i;
  677. }
  678. /* mask \+symbol and convert '\t' to ' ' */
  679. for (i = j = 0; matchBuf[i]; i++, j++)
  680. if (matchBuf[i] == '\\') {
  681. collapse_pos(j, j + 1);
  682. int_buf[j] |= QUOT;
  683. i++;
  684. #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
  685. if (matchBuf[i] == '\t') /* algorithm equivalent */
  686. int_buf[j] = ' ' | QUOT;
  687. #endif
  688. }
  689. #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
  690. else if (matchBuf[i] == '\t')
  691. int_buf[j] = ' ';
  692. #endif
  693. /* mask "symbols" or 'symbols' */
  694. c2 = 0;
  695. for (i = 0; int_buf[i]; i++) {
  696. c = int_buf[i];
  697. if (c == '\'' || c == '"') {
  698. if (c2 == 0)
  699. c2 = c;
  700. else {
  701. if (c == c2)
  702. c2 = 0;
  703. else
  704. int_buf[i] |= QUOT;
  705. }
  706. } else if (c2 != 0 && c != '$')
  707. int_buf[i] |= QUOT;
  708. }
  709. /* skip commands with arguments if line has commands delimiters */
  710. /* ';' ';;' '&' '|' '&&' '||' but `>&' `<&' `>|' */
  711. for (i = 0; int_buf[i]; i++) {
  712. c = int_buf[i];
  713. c2 = int_buf[i + 1];
  714. j = i ? int_buf[i - 1] : -1;
  715. command_mode = 0;
  716. if (c == ';' || c == '&' || c == '|') {
  717. command_mode = 1 + (c == c2);
  718. if (c == '&') {
  719. if (j == '>' || j == '<')
  720. command_mode = 0;
  721. } else if (c == '|' && j == '>')
  722. command_mode = 0;
  723. }
  724. if (command_mode) {
  725. collapse_pos(0, i + command_mode);
  726. i = -1; /* hack incremet */
  727. }
  728. }
  729. /* collapse `command...` */
  730. for (i = 0; int_buf[i]; i++) {
  731. if (int_buf[i] == '`') {
  732. for (j = i + 1; int_buf[j]; j++)
  733. if (int_buf[j] == '`') {
  734. collapse_pos(i, j + 1);
  735. j = 0;
  736. break;
  737. }
  738. if (j) {
  739. /* not found closing ` - command mode, collapse all previous */
  740. collapse_pos(0, i + 1);
  741. break;
  742. } else
  743. i--; /* hack incremet */
  744. }
  745. }
  746. /* collapse (command...(command...)...) or {command...{command...}...} */
  747. c = 0; /* "recursive" level */
  748. c2 = 0;
  749. for (i = 0; int_buf[i]; i++) {
  750. if (int_buf[i] == '(' || int_buf[i] == '{') {
  751. if (int_buf[i] == '(')
  752. c++;
  753. else
  754. c2++;
  755. collapse_pos(0, i + 1);
  756. i = -1; /* hack incremet */
  757. }
  758. }
  759. for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++) {
  760. if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) {
  761. if (int_buf[i] == ')')
  762. c--;
  763. else
  764. c2--;
  765. collapse_pos(0, i + 1);
  766. i = -1; /* hack incremet */
  767. }
  768. }
  769. /* skip first not quote space */
  770. for (i = 0; int_buf[i]; i++)
  771. if (int_buf[i] != ' ')
  772. break;
  773. if (i)
  774. collapse_pos(0, i);
  775. /* set find mode for completion */
  776. command_mode = FIND_EXE_ONLY;
  777. for (i = 0; int_buf[i]; i++) {
  778. if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') {
  779. if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY
  780. && matchBuf[pos_buf[0]] == 'c'
  781. && matchBuf[pos_buf[1]] == 'd'
  782. ) {
  783. command_mode = FIND_DIR_ONLY;
  784. } else {
  785. command_mode = FIND_FILE_ONLY;
  786. break;
  787. }
  788. }
  789. }
  790. for (i = 0; int_buf[i]; i++)
  791. /* "strlen" */;
  792. /* find last word */
  793. for (--i; i >= 0; i--) {
  794. c = int_buf[i];
  795. if (c == ' ' || c == '<' || c == '>' || c == '|' || c == '&') {
  796. collapse_pos(0, i + 1);
  797. break;
  798. }
  799. }
  800. /* skip first not quoted '\'' or '"' */
  801. for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++)
  802. /*skip*/;
  803. /* collapse quote or unquote // or /~ */
  804. while ((int_buf[i] & ~QUOT) == '/'
  805. && ((int_buf[i+1] & ~QUOT) == '/' || (int_buf[i+1] & ~QUOT) == '~')
  806. ) {
  807. i++;
  808. }
  809. /* set only match and destroy quotes */
  810. j = 0;
  811. for (c = 0; pos_buf[i] >= 0; i++) {
  812. matchBuf[c++] = matchBuf[pos_buf[i]];
  813. j = pos_buf[i] + 1;
  814. }
  815. matchBuf[c] = '\0';
  816. /* old length matchBuf with quotes symbols */
  817. *len_with_quotes = j ? j - pos_buf[0] : 0;
  818. return command_mode;
  819. }
  820. #undef int_buf
  821. #undef pos_buf
  822. /*
  823. * display by column (original idea from ls applet,
  824. * very optimized by me :)
  825. */
  826. static void showfiles(void)
  827. {
  828. int ncols, row;
  829. int column_width = 0;
  830. int nfiles = num_matches;
  831. int nrows = nfiles;
  832. int l;
  833. /* find the longest file name - use that as the column width */
  834. for (row = 0; row < nrows; row++) {
  835. l = unicode_strlen(matches[row]);
  836. if (column_width < l)
  837. column_width = l;
  838. }
  839. column_width += 2; /* min space for columns */
  840. ncols = cmdedit_termw / column_width;
  841. if (ncols > 1) {
  842. nrows /= ncols;
  843. if (nfiles % ncols)
  844. nrows++; /* round up fractionals */
  845. } else {
  846. ncols = 1;
  847. }
  848. for (row = 0; row < nrows; row++) {
  849. int n = row;
  850. int nc;
  851. for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
  852. printf("%s%-*s", matches[n],
  853. (int)(column_width - unicode_strlen(matches[n])), ""
  854. );
  855. }
  856. puts(matches[n]);
  857. }
  858. }
  859. static char *add_quote_for_spec_chars(char *found)
  860. {
  861. int l = 0;
  862. char *s = xzalloc((strlen(found) + 1) * 2);
  863. while (*found) {
  864. if (strchr(" `\"#$%^&*()=+{}[]:;'|\\<>", *found))
  865. s[l++] = '\\';
  866. s[l++] = *found++;
  867. }
  868. /* s[l] = '\0'; - already is */
  869. return s;
  870. }
  871. /* Do TAB completion */
  872. static void input_tab(smallint *lastWasTab)
  873. {
  874. if (!(state->flags & TAB_COMPLETION))
  875. return;
  876. if (!*lastWasTab) {
  877. char *tmp, *tmp1;
  878. size_t len_found;
  879. /* char matchBuf[MAX_LINELEN]; */
  880. #define matchBuf (S.input_tab__matchBuf)
  881. int find_type;
  882. int recalc_pos;
  883. #if ENABLE_UNICODE_SUPPORT
  884. /* cursor pos in command converted to multibyte form */
  885. int cursor_mb;
  886. #endif
  887. *lastWasTab = TRUE; /* flop trigger */
  888. /* Make a local copy of the string --
  889. * up to the position of the cursor */
  890. save_string(matchBuf, cursor + 1);
  891. #if ENABLE_UNICODE_SUPPORT
  892. cursor_mb = strlen(matchBuf);
  893. #endif
  894. tmp = matchBuf;
  895. find_type = find_match(matchBuf, &recalc_pos);
  896. /* Free up any memory already allocated */
  897. free_tab_completion_data();
  898. #if ENABLE_FEATURE_USERNAME_COMPLETION
  899. /* If the word starts with `~' and there is no slash in the word,
  900. * then try completing this word as a username. */
  901. if (state->flags & USERNAME_COMPLETION)
  902. if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL)
  903. username_tab_completion(matchBuf, NULL);
  904. #endif
  905. /* Try to match any executable in our path and everything
  906. * in the current working directory */
  907. if (!matches)
  908. exe_n_cwd_tab_completion(matchBuf, find_type);
  909. /* Sort, then remove any duplicates found */
  910. if (matches) {
  911. unsigned i;
  912. int n = 0;
  913. qsort_string_vector(matches, num_matches);
  914. for (i = 0; i < num_matches - 1; ++i) {
  915. if (matches[i] && matches[i+1]) { /* paranoia */
  916. if (strcmp(matches[i], matches[i+1]) == 0) {
  917. free(matches[i]);
  918. matches[i] = NULL; /* paranoia */
  919. } else {
  920. matches[n++] = matches[i];
  921. }
  922. }
  923. }
  924. matches[n] = matches[i];
  925. num_matches = n + 1;
  926. }
  927. /* Did we find exactly one match? */
  928. if (!matches || num_matches > 1) { /* no */
  929. beep();
  930. if (!matches)
  931. return; /* not found */
  932. /* find minimal match */
  933. tmp1 = xstrdup(matches[0]);
  934. for (tmp = tmp1; *tmp; tmp++) {
  935. for (len_found = 1; len_found < num_matches; len_found++) {
  936. if (matches[len_found][tmp - tmp1] != *tmp) {
  937. *tmp = '\0';
  938. break;
  939. }
  940. }
  941. }
  942. if (*tmp1 == '\0') { /* have unique */
  943. free(tmp1);
  944. return;
  945. }
  946. tmp = add_quote_for_spec_chars(tmp1);
  947. free(tmp1);
  948. } else { /* one match */
  949. tmp = add_quote_for_spec_chars(matches[0]);
  950. /* for next completion current found */
  951. *lastWasTab = FALSE;
  952. len_found = strlen(tmp);
  953. if (tmp[len_found-1] != '/') {
  954. tmp[len_found] = ' ';
  955. tmp[len_found+1] = '\0';
  956. }
  957. }
  958. len_found = strlen(tmp);
  959. #if !ENABLE_UNICODE_SUPPORT
  960. /* have space to place the match? */
  961. /* The result consists of three parts with these lengths: */
  962. /* (cursor - recalc_pos) + len_found + (command_len - cursor) */
  963. /* it simplifies into: */
  964. if ((int)(len_found + command_len - recalc_pos) < S.maxsize) {
  965. /* save tail */
  966. strcpy(matchBuf, command_ps + cursor);
  967. /* add match and tail */
  968. sprintf(&command_ps[cursor - recalc_pos], "%s%s", tmp, matchBuf);
  969. command_len = strlen(command_ps);
  970. /* new pos */
  971. recalc_pos = cursor - recalc_pos + len_found;
  972. /* write out the matched command */
  973. redraw(cmdedit_y, command_len - recalc_pos);
  974. }
  975. #else
  976. {
  977. char command[MAX_LINELEN];
  978. int len = save_string(command, sizeof(command));
  979. /* have space to place the match? */
  980. /* (cursor_mb - recalc_pos) + len_found + (len - cursor_mb) */
  981. if ((int)(len_found + len - recalc_pos) < MAX_LINELEN) {
  982. /* save tail */
  983. strcpy(matchBuf, command + cursor_mb);
  984. /* where do we want to have cursor after all? */
  985. strcpy(&command[cursor_mb - recalc_pos], tmp);
  986. len = load_string(command, S.maxsize);
  987. /* add match and tail */
  988. sprintf(&command[cursor_mb - recalc_pos], "%s%s", tmp, matchBuf);
  989. command_len = load_string(command, S.maxsize);
  990. /* write out the matched command */
  991. redraw(cmdedit_y, command_len - len);
  992. }
  993. }
  994. #endif
  995. free(tmp);
  996. #undef matchBuf
  997. } else {
  998. /* Ok -- the last char was a TAB. Since they
  999. * just hit TAB again, print a list of all the
  1000. * available choices... */
  1001. if (matches && num_matches > 0) {
  1002. /* changed by goto_new_line() */
  1003. int sav_cursor = cursor;
  1004. /* Go to the next line */
  1005. goto_new_line();
  1006. showfiles();
  1007. redraw(0, command_len - sav_cursor);
  1008. }
  1009. }
  1010. }
  1011. #endif /* FEATURE_COMMAND_TAB_COMPLETION */
  1012. line_input_t* FAST_FUNC new_line_input_t(int flags)
  1013. {
  1014. line_input_t *n = xzalloc(sizeof(*n));
  1015. n->flags = flags;
  1016. return n;
  1017. }
  1018. #if MAX_HISTORY > 0
  1019. static void save_command_ps_at_cur_history(void)
  1020. {
  1021. if (command_ps[0] != BB_NUL) {
  1022. int cur = state->cur_history;
  1023. free(state->history[cur]);
  1024. # if ENABLE_UNICODE_SUPPORT
  1025. {
  1026. char tbuf[MAX_LINELEN];
  1027. save_string(tbuf, sizeof(tbuf));
  1028. state->history[cur] = xstrdup(tbuf);
  1029. }
  1030. # else
  1031. state->history[cur] = xstrdup(command_ps);
  1032. # endif
  1033. }
  1034. }
  1035. /* state->flags is already checked to be nonzero */
  1036. static int get_previous_history(void)
  1037. {
  1038. if ((state->flags & DO_HISTORY) && state->cur_history) {
  1039. save_command_ps_at_cur_history();
  1040. state->cur_history--;
  1041. return 1;
  1042. }
  1043. beep();
  1044. return 0;
  1045. }
  1046. static int get_next_history(void)
  1047. {
  1048. if (state->flags & DO_HISTORY) {
  1049. if (state->cur_history < state->cnt_history) {
  1050. save_command_ps_at_cur_history(); /* save the current history line */
  1051. return ++state->cur_history;
  1052. }
  1053. }
  1054. beep();
  1055. return 0;
  1056. }
  1057. # if ENABLE_FEATURE_EDITING_SAVEHISTORY
  1058. /* We try to ensure that concurrent additions to the history
  1059. * do not overwrite each other.
  1060. * Otherwise shell users get unhappy.
  1061. *
  1062. * History file is trimmed lazily, when it grows several times longer
  1063. * than configured MAX_HISTORY lines.
  1064. */
  1065. static void free_line_input_t(line_input_t *n)
  1066. {
  1067. int i = n->cnt_history;
  1068. while (i > 0)
  1069. free(n->history[--i]);
  1070. free(n);
  1071. }
  1072. /* state->flags is already checked to be nonzero */
  1073. static void load_history(line_input_t *st_parm)
  1074. {
  1075. char *temp_h[MAX_HISTORY];
  1076. char *line;
  1077. FILE *fp;
  1078. unsigned idx, i, line_len;
  1079. /* NB: do not trash old history if file can't be opened */
  1080. fp = fopen_for_read(st_parm->hist_file);
  1081. if (fp) {
  1082. /* clean up old history */
  1083. for (idx = st_parm->cnt_history; idx > 0;) {
  1084. idx--;
  1085. free(st_parm->history[idx]);
  1086. st_parm->history[idx] = NULL;
  1087. }
  1088. /* fill temp_h[], retaining only last MAX_HISTORY lines */
  1089. memset(temp_h, 0, sizeof(temp_h));
  1090. st_parm->cnt_history_in_file = idx = 0;
  1091. while ((line = xmalloc_fgetline(fp)) != NULL) {
  1092. if (line[0] == '\0') {
  1093. free(line);
  1094. continue;
  1095. }
  1096. free(temp_h[idx]);
  1097. temp_h[idx] = line;
  1098. st_parm->cnt_history_in_file++;
  1099. idx++;
  1100. if (idx == MAX_HISTORY)
  1101. idx = 0;
  1102. }
  1103. fclose(fp);
  1104. /* find first non-NULL temp_h[], if any */
  1105. if (st_parm->cnt_history_in_file) {
  1106. while (temp_h[idx] == NULL) {
  1107. idx++;
  1108. if (idx == MAX_HISTORY)
  1109. idx = 0;
  1110. }
  1111. }
  1112. /* copy temp_h[] to st_parm->history[] */
  1113. for (i = 0; i < MAX_HISTORY;) {
  1114. line = temp_h[idx];
  1115. if (!line)
  1116. break;
  1117. idx++;
  1118. if (idx == MAX_HISTORY)
  1119. idx = 0;
  1120. line_len = strlen(line);
  1121. if (line_len >= MAX_LINELEN)
  1122. line[MAX_LINELEN-1] = '\0';
  1123. st_parm->history[i++] = line;
  1124. }
  1125. st_parm->cnt_history = i;
  1126. }
  1127. }
  1128. /* state->flags is already checked to be nonzero */
  1129. static void save_history(char *str)
  1130. {
  1131. int fd;
  1132. int len, len2;
  1133. fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0666);
  1134. if (fd < 0)
  1135. return;
  1136. xlseek(fd, 0, SEEK_END); /* paranoia */
  1137. len = strlen(str);
  1138. str[len] = '\n'; /* we (try to) do atomic write */
  1139. len2 = full_write(fd, str, len + 1);
  1140. str[len] = '\0';
  1141. close(fd);
  1142. if (len2 != len + 1)
  1143. return; /* "wtf?" */
  1144. /* did we write so much that history file needs trimming? */
  1145. state->cnt_history_in_file++;
  1146. if (state->cnt_history_in_file > MAX_HISTORY * 4) {
  1147. FILE *fp;
  1148. char *new_name;
  1149. line_input_t *st_temp;
  1150. int i;
  1151. /* we may have concurrently written entries from others.
  1152. * load them */
  1153. st_temp = new_line_input_t(state->flags);
  1154. st_temp->hist_file = state->hist_file;
  1155. load_history(st_temp);
  1156. /* write out temp file and replace hist_file atomically */
  1157. new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid());
  1158. fp = fopen_for_write(new_name);
  1159. if (fp) {
  1160. for (i = 0; i < st_temp->cnt_history; i++)
  1161. fprintf(fp, "%s\n", st_temp->history[i]);
  1162. fclose(fp);
  1163. if (rename(new_name, state->hist_file) == 0)
  1164. state->cnt_history_in_file = st_temp->cnt_history;
  1165. }
  1166. free(new_name);
  1167. free_line_input_t(st_temp);
  1168. }
  1169. }
  1170. # else
  1171. # define load_history(a) ((void)0)
  1172. # define save_history(a) ((void)0)
  1173. # endif /* FEATURE_COMMAND_SAVEHISTORY */
  1174. static void remember_in_history(char *str)
  1175. {
  1176. int i;
  1177. if (!(state->flags & DO_HISTORY))
  1178. return;
  1179. if (str[0] == '\0')
  1180. return;
  1181. i = state->cnt_history;
  1182. /* Don't save dupes */
  1183. if (i && strcmp(state->history[i-1], str) == 0)
  1184. return;
  1185. free(state->history[MAX_HISTORY]); /* redundant, paranoia */
  1186. state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
  1187. /* If history[] is full, remove the oldest command */
  1188. /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
  1189. if (i >= MAX_HISTORY) {
  1190. free(state->history[0]);
  1191. for (i = 0; i < MAX_HISTORY-1; i++)
  1192. state->history[i] = state->history[i+1];
  1193. /* i == MAX_HISTORY-1 */
  1194. }
  1195. /* i <= MAX_HISTORY-1 */
  1196. state->history[i++] = xstrdup(str);
  1197. /* i <= MAX_HISTORY */
  1198. state->cur_history = i;
  1199. state->cnt_history = i;
  1200. # if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
  1201. if ((state->flags & SAVE_HISTORY) && state->hist_file)
  1202. save_history(str);
  1203. # endif
  1204. IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
  1205. }
  1206. #else /* MAX_HISTORY == 0 */
  1207. # define remember_in_history(a) ((void)0)
  1208. #endif /* MAX_HISTORY */
  1209. #if ENABLE_FEATURE_EDITING_VI
  1210. /*
  1211. * vi mode implemented 2005 by Paul Fox <pgf@foxharp.boston.ma.us>
  1212. */
  1213. static void
  1214. vi_Word_motion(int eat)
  1215. {
  1216. CHAR_T *command = command_ps;
  1217. while (cursor < command_len && !BB_isspace(command[cursor]))
  1218. input_forward();
  1219. if (eat) while (cursor < command_len && BB_isspace(command[cursor]))
  1220. input_forward();
  1221. }
  1222. static void
  1223. vi_word_motion(int eat)
  1224. {
  1225. CHAR_T *command = command_ps;
  1226. if (BB_isalnum(command[cursor]) || command[cursor] == '_') {
  1227. while (cursor < command_len
  1228. && (BB_isalnum(command[cursor+1]) || command[cursor+1] == '_')
  1229. ) {
  1230. input_forward();
  1231. }
  1232. } else if (BB_ispunct(command[cursor])) {
  1233. while (cursor < command_len && BB_ispunct(command[cursor+1]))
  1234. input_forward();
  1235. }
  1236. if (cursor < command_len)
  1237. input_forward();
  1238. if (eat) {
  1239. while (cursor < command_len && BB_isspace(command[cursor]))
  1240. input_forward();
  1241. }
  1242. }
  1243. static void
  1244. vi_End_motion(void)
  1245. {
  1246. CHAR_T *command = command_ps;
  1247. input_forward();
  1248. while (cursor < command_len && BB_isspace(command[cursor]))
  1249. input_forward();
  1250. while (cursor < command_len-1 && !BB_isspace(command[cursor+1]))
  1251. input_forward();
  1252. }
  1253. static void
  1254. vi_end_motion(void)
  1255. {
  1256. CHAR_T *command = command_ps;
  1257. if (cursor >= command_len-1)
  1258. return;
  1259. input_forward();
  1260. while (cursor < command_len-1 && BB_isspace(command[cursor]))
  1261. input_forward();
  1262. if (cursor >= command_len-1)
  1263. return;
  1264. if (BB_isalnum(command[cursor]) || command[cursor] == '_') {
  1265. while (cursor < command_len-1
  1266. && (BB_isalnum(command[cursor+1]) || command[cursor+1] == '_')
  1267. ) {
  1268. input_forward();
  1269. }
  1270. } else if (BB_ispunct(command[cursor])) {
  1271. while (cursor < command_len-1 && BB_ispunct(command[cursor+1]))
  1272. input_forward();
  1273. }
  1274. }
  1275. static void
  1276. vi_Back_motion(void)
  1277. {
  1278. CHAR_T *command = command_ps;
  1279. while (cursor > 0 && BB_isspace(command[cursor-1]))
  1280. input_backward(1);
  1281. while (cursor > 0 && !BB_isspace(command[cursor-1]))
  1282. input_backward(1);
  1283. }
  1284. static void
  1285. vi_back_motion(void)
  1286. {
  1287. CHAR_T *command = command_ps;
  1288. if (cursor <= 0)
  1289. return;
  1290. input_backward(1);
  1291. while (cursor > 0 && BB_isspace(command[cursor]))
  1292. input_backward(1);
  1293. if (cursor <= 0)
  1294. return;
  1295. if (BB_isalnum(command[cursor]) || command[cursor] == '_') {
  1296. while (cursor > 0
  1297. && (BB_isalnum(command[cursor-1]) || command[cursor-1] == '_')
  1298. ) {
  1299. input_backward(1);
  1300. }
  1301. } else if (BB_ispunct(command[cursor])) {
  1302. while (cursor > 0 && BB_ispunct(command[cursor-1]))
  1303. input_backward(1);
  1304. }
  1305. }
  1306. #endif
  1307. /* Modelled after bash 4.0 behavior of Ctrl-<arrow> */
  1308. static void ctrl_left(void)
  1309. {
  1310. CHAR_T *command = command_ps;
  1311. while (1) {
  1312. CHAR_T c;
  1313. input_backward(1);
  1314. if (cursor == 0)
  1315. break;
  1316. c = command[cursor];
  1317. if (c != ' ' && !BB_ispunct(c)) {
  1318. /* we reached a "word" delimited by spaces/punct.
  1319. * go to its beginning */
  1320. while (1) {
  1321. c = command[cursor - 1];
  1322. if (c == ' ' || BB_ispunct(c))
  1323. break;
  1324. input_backward(1);
  1325. if (cursor == 0)
  1326. break;
  1327. }
  1328. break;
  1329. }
  1330. }
  1331. }
  1332. static void ctrl_right(void)
  1333. {
  1334. CHAR_T *command = command_ps;
  1335. while (1) {
  1336. CHAR_T c;
  1337. c = command[cursor];
  1338. if (c == BB_NUL)
  1339. break;
  1340. if (c != ' ' && !BB_ispunct(c)) {
  1341. /* we reached a "word" delimited by spaces/punct.
  1342. * go to its end + 1 */
  1343. while (1) {
  1344. input_forward();
  1345. c = command[cursor];
  1346. if (c == BB_NUL || c == ' ' || BB_ispunct(c))
  1347. break;
  1348. }
  1349. break;
  1350. }
  1351. input_forward();
  1352. }
  1353. }
  1354. /*
  1355. * read_line_input and its helpers
  1356. */
  1357. #if ENABLE_FEATURE_EDITING_ASK_TERMINAL
  1358. static void ask_terminal(void)
  1359. {
  1360. /* Ask terminal where is the cursor now.
  1361. * lineedit_read_key handles response and corrects
  1362. * our idea of current cursor position.
  1363. * Testcase: run "echo -n long_line_long_line_long_line",
  1364. * then type in a long, wrapping command and try to
  1365. * delete it using backspace key.
  1366. * Note: we print it _after_ prompt, because
  1367. * prompt may contain CR. Example: PS1='\[\r\n\]\w '
  1368. */
  1369. /* Problem: if there is buffered input on stdin,
  1370. * the response will be delivered later,
  1371. * possibly to an unsuspecting application.
  1372. * Testcase: "sleep 1; busybox ash" + press and hold [Enter].
  1373. * Result:
  1374. * ~/srcdevel/bbox/fix/busybox.t4 #
  1375. * ~/srcdevel/bbox/fix/busybox.t4 #
  1376. * ^[[59;34~/srcdevel/bbox/fix/busybox.t4 # <-- garbage
  1377. * ~/srcdevel/bbox/fix/busybox.t4 #
  1378. *
  1379. * Checking for input with poll only makes the race narrower,
  1380. * I still can trigger it. Strace:
  1381. *
  1382. * write(1, "~/srcdevel/bbox/fix/busybox.t4 # ", 33) = 33
  1383. * poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) <-- no input exists
  1384. * write(1, "\33[6n", 4) = 4 <-- send the ESC sequence, quick!
  1385. * poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1 ([{fd=0, revents=POLLIN}])
  1386. * read(0, "\n", 1) = 1 <-- oh crap, user's input got in first
  1387. */
  1388. struct pollfd pfd;
  1389. pfd.fd = STDIN_FILENO;
  1390. pfd.events = POLLIN;
  1391. if (safe_poll(&pfd, 1, 0) == 0) {
  1392. S.sent_ESC_br6n = 1;
  1393. out1str("\033" "[6n");
  1394. fflush_all(); /* make terminal see it ASAP! */
  1395. }
  1396. }
  1397. #else
  1398. #define ask_terminal() ((void)0)
  1399. #endif
  1400. #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
  1401. static void parse_and_put_prompt(const char *prmt_ptr)
  1402. {
  1403. cmdedit_prompt = prmt_ptr;
  1404. cmdedit_prmt_len = strlen(prmt_ptr);
  1405. put_prompt();
  1406. }
  1407. #else
  1408. static void parse_and_put_prompt(const char *prmt_ptr)
  1409. {
  1410. int prmt_len = 0;
  1411. size_t cur_prmt_len = 0;
  1412. char flg_not_length = '[';
  1413. char *prmt_mem_ptr = xzalloc(1);
  1414. char *cwd_buf = xrealloc_getcwd_or_warn(NULL);
  1415. char cbuf[2];
  1416. char c;
  1417. char *pbuf;
  1418. cmdedit_prmt_len = 0;
  1419. if (!cwd_buf) {
  1420. cwd_buf = (char *)bb_msg_unknown;
  1421. }
  1422. cbuf[1] = '\0'; /* never changes */
  1423. while (*prmt_ptr) {
  1424. char *free_me = NULL;
  1425. pbuf = cbuf;
  1426. c = *prmt_ptr++;
  1427. if (c == '\\') {
  1428. const char *cp = prmt_ptr;
  1429. int l;
  1430. c = bb_process_escape_sequence(&prmt_ptr);
  1431. if (prmt_ptr == cp) {
  1432. if (*cp == '\0')
  1433. break;
  1434. c = *prmt_ptr++;
  1435. switch (c) {
  1436. # if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  1437. case 'u':
  1438. pbuf = user_buf ? user_buf : (char*)"";
  1439. break;
  1440. # endif
  1441. case 'h':
  1442. pbuf = free_me = safe_gethostname();
  1443. *strchrnul(pbuf, '.') = '\0';
  1444. break;
  1445. case '$':
  1446. c = (geteuid() == 0 ? '#' : '$');
  1447. break;
  1448. # if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  1449. case 'w':
  1450. /* /home/user[/something] -> ~[/something] */
  1451. pbuf = cwd_buf;
  1452. l = strlen(home_pwd_buf);
  1453. if (l != 0
  1454. && strncmp(home_pwd_buf, cwd_buf, l) == 0
  1455. && (cwd_buf[l]=='/' || cwd_buf[l]=='\0')
  1456. && strlen(cwd_buf + l) < PATH_MAX
  1457. ) {
  1458. pbuf = free_me = xasprintf("~%s", cwd_buf + l);
  1459. }
  1460. break;
  1461. # endif
  1462. case 'W':
  1463. pbuf = cwd_buf;
  1464. cp = strrchr(pbuf, '/');
  1465. if (cp != NULL && cp != pbuf)
  1466. pbuf += (cp-pbuf) + 1;
  1467. break;
  1468. case '!':
  1469. pbuf = free_me = xasprintf("%d", num_ok_lines);
  1470. break;
  1471. case 'e': case 'E': /* \e \E = \033 */
  1472. c = '\033';
  1473. break;
  1474. case 'x': case 'X': {
  1475. char buf2[4];
  1476. for (l = 0; l < 3;) {
  1477. unsigned h;
  1478. buf2[l++] = *prmt_ptr;
  1479. buf2[l] = '\0';
  1480. h = strtoul(buf2, &pbuf, 16);
  1481. if (h > UCHAR_MAX || (pbuf - buf2) < l) {
  1482. buf2[--l] = '\0';
  1483. break;
  1484. }
  1485. prmt_ptr++;
  1486. }
  1487. c = (char)strtoul(buf2, NULL, 16);
  1488. if (c == 0)
  1489. c = '?';
  1490. pbuf = cbuf;
  1491. break;
  1492. }
  1493. case '[': case ']':
  1494. if (c == flg_not_length) {
  1495. flg_not_length = (flg_not_length == '[' ? ']' : '[');
  1496. continue;
  1497. }
  1498. break;
  1499. } /* switch */
  1500. } /* if */
  1501. } /* if */
  1502. cbuf[0] = c;
  1503. cur_prmt_len = strlen(pbuf);
  1504. prmt_len += cur_prmt_len;
  1505. if (flg_not_length != ']')
  1506. cmdedit_prmt_len += cur_prmt_len;
  1507. prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
  1508. free(free_me);
  1509. } /* while */
  1510. if (cwd_buf != (char *)bb_msg_unknown)
  1511. free(cwd_buf);
  1512. cmdedit_prompt = prmt_mem_ptr;
  1513. put_prompt();
  1514. }
  1515. #endif
  1516. static void cmdedit_setwidth(unsigned w, int redraw_flg)
  1517. {
  1518. cmdedit_termw = w;
  1519. if (redraw_flg) {
  1520. /* new y for current cursor */
  1521. int new_y = (cursor + cmdedit_prmt_len) / w;
  1522. /* redraw */
  1523. redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), command_len - cursor);
  1524. fflush_all();
  1525. }
  1526. }
  1527. static void win_changed(int nsig)
  1528. {
  1529. unsigned width;
  1530. get_terminal_width_height(0, &width, NULL);
  1531. cmdedit_setwidth(width, nsig /* - just a yes/no flag */);
  1532. if (nsig == SIGWINCH)
  1533. signal(SIGWINCH, win_changed); /* rearm ourself */
  1534. }
  1535. static int lineedit_read_key(char *read_key_buffer)
  1536. {
  1537. int64_t ic;
  1538. int timeout = -1;
  1539. #if ENABLE_UNICODE_SUPPORT
  1540. char unicode_buf[MB_CUR_MAX + 1];
  1541. int unicode_idx = 0;
  1542. #endif
  1543. while (1) {
  1544. /* Wait for input. TIMEOUT = -1 makes read_key wait even
  1545. * on nonblocking stdin, TIMEOUT = 50 makes sure we won't
  1546. * insist on full MB_CUR_MAX buffer to declare input like
  1547. * "\xff\n",pause,"ls\n" invalid and thus won't lose "ls".
  1548. *
  1549. * Note: read_key sets errno to 0 on success.
  1550. */
  1551. ic = read_key(STDIN_FILENO, read_key_buffer, timeout);
  1552. if (errno) {
  1553. #if ENABLE_UNICODE_SUPPORT
  1554. if (errno == EAGAIN && unicode_idx != 0)
  1555. goto pushback;
  1556. #endif
  1557. break;
  1558. }
  1559. #if ENABLE_FEATURE_EDITING_ASK_TERMINAL
  1560. if ((int32_t)ic == KEYCODE_CURSOR_POS
  1561. && S.sent_ESC_br6n
  1562. ) {
  1563. S.sent_ESC_br6n = 0;
  1564. if (cursor == 0) { /* otherwise it may be bogus */
  1565. int col = ((ic >> 32) & 0x7fff) - 1;
  1566. if (col > cmdedit_prmt_len) {
  1567. cmdedit_x += (col - cmdedit_prmt_len);
  1568. while (cmdedit_x >= cmdedit_termw) {
  1569. cmdedit_x -= cmdedit_termw;
  1570. cmdedit_y++;
  1571. }
  1572. }
  1573. }
  1574. continue;
  1575. }
  1576. #endif
  1577. #if ENABLE_UNICODE_SUPPORT
  1578. if (unicode_status == UNICODE_ON) {
  1579. wchar_t wc;
  1580. if ((int32_t)ic < 0) /* KEYCODE_xxx */
  1581. break;
  1582. // TODO: imagine sequence like: 0xff,<left-arrow>: we are currently losing 0xff...
  1583. unicode_buf[unicode_idx++] = ic;
  1584. unicode_buf[unicode_idx] = '\0';
  1585. if (mbstowcs(&wc, unicode_buf, 1) != 1) {
  1586. /* Not (yet?) a valid unicode char */
  1587. if (unicode_idx < MB_CUR_MAX) {
  1588. timeout = 50;
  1589. continue;
  1590. }
  1591. pushback:
  1592. /* Invalid sequence. Save all "bad bytes" except first */
  1593. read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1);
  1594. # if !ENABLE_UNICODE_PRESERVE_BROKEN
  1595. ic = CONFIG_SUBST_WCHAR;
  1596. # else
  1597. ic = unicode_mark_inv_wchar(unicode_buf[0]);
  1598. # endif
  1599. } else {
  1600. /* Valid unicode char, return its code */
  1601. ic = wc;
  1602. }
  1603. }
  1604. #endif
  1605. break;
  1606. }
  1607. return ic;
  1608. }
  1609. #if ENABLE_UNICODE_BIDI_SUPPORT
  1610. static int isrtl_str(void)
  1611. {
  1612. int idx = cursor;
  1613. while (idx < command_len && unicode_bidi_is_neutral_wchar(command_ps[idx]))
  1614. idx++;
  1615. return unicode_bidi_isrtl(command_ps[idx]);
  1616. }
  1617. #else
  1618. # define isrtl_str() 0
  1619. #endif
  1620. /* leave out the "vi-mode"-only case labels if vi editing isn't
  1621. * configured. */
  1622. #define vi_case(caselabel) IF_FEATURE_EDITING_VI(case caselabel)
  1623. /* convert uppercase ascii to equivalent control char, for readability */
  1624. #undef CTRL
  1625. #define CTRL(a) ((a) & ~0x40)
  1626. /* maxsize must be >= 2.
  1627. * Returns:
  1628. * -1 on read errors or EOF, or on bare Ctrl-D,
  1629. * 0 on ctrl-C (the line entered is still returned in 'command'),
  1630. * >0 length of input string, including terminating '\n'
  1631. */
  1632. int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
  1633. {
  1634. int len;
  1635. #if ENABLE_FEATURE_TAB_COMPLETION
  1636. smallint lastWasTab = FALSE;
  1637. #endif
  1638. smallint break_out = 0;
  1639. #if ENABLE_FEATURE_EDITING_VI
  1640. smallint vi_cmdmode = 0;
  1641. #endif
  1642. struct termios initial_settings;
  1643. struct termios new_settings;
  1644. char read_key_buffer[KEYCODE_BUFFER_SIZE];
  1645. INIT_S();
  1646. if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
  1647. || !(initial_settings.c_lflag & ECHO)
  1648. ) {
  1649. /* Happens when e.g. stty -echo was run before */
  1650. parse_and_put_prompt(prompt);
  1651. /* fflush_all(); - done by parse_and_put_prompt */
  1652. if (fgets(command, maxsize, stdin) == NULL)
  1653. len = -1; /* EOF or error */
  1654. else
  1655. len = strlen(command);
  1656. DEINIT_S();
  1657. return len;
  1658. }
  1659. init_unicode();
  1660. // FIXME: audit & improve this
  1661. if (maxsize > MAX_LINELEN)
  1662. maxsize = MAX_LINELEN;
  1663. S.maxsize = maxsize;
  1664. /* With null flags, no other fields are ever used */
  1665. state = st ? st : (line_input_t*) &const_int_0;
  1666. #if MAX_HISTORY > 0
  1667. # if ENABLE_FEATURE_EDITING_SAVEHISTORY
  1668. if ((state->flags & SAVE_HISTORY) && state->hist_file)
  1669. if (state->cnt_history == 0)
  1670. load_history(state);
  1671. # endif
  1672. if (state->flags & DO_HISTORY)
  1673. state->cur_history = state->cnt_history;
  1674. #endif
  1675. /* prepare before init handlers */
  1676. cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
  1677. command_len = 0;
  1678. #if ENABLE_UNICODE_SUPPORT
  1679. command_ps = xzalloc(maxsize * sizeof(command_ps[0]));
  1680. #else
  1681. command_ps = command;
  1682. command[0] = '\0';
  1683. #endif
  1684. #define command command_must_not_be_used
  1685. new_settings = initial_settings;
  1686. new_settings.c_lflag &= ~ICANON; /* unbuffered input */
  1687. /* Turn off echoing and CTRL-C, so we can trap it */
  1688. new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
  1689. /* Hmm, in linux c_cc[] is not parsed if ICANON is off */
  1690. new_settings.c_cc[VMIN] = 1;
  1691. new_settings.c_cc[VTIME] = 0;
  1692. /* Turn off CTRL-C, so we can trap it */
  1693. #ifndef _POSIX_VDISABLE
  1694. # define _POSIX_VDISABLE '\0'
  1695. #endif
  1696. new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
  1697. tcsetattr_stdin_TCSANOW(&new_settings);
  1698. /* Now initialize things */
  1699. previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
  1700. win_changed(0); /* do initial resizing */
  1701. #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
  1702. {
  1703. struct passwd *entry;
  1704. entry = getpwuid(geteuid());
  1705. if (entry) {
  1706. user_buf = xstrdup(entry->pw_name);
  1707. home_pwd_buf = xstrdup(entry->pw_dir);
  1708. }
  1709. }
  1710. #endif
  1711. #if 0
  1712. for (i = 0; i <= MAX_HISTORY; i++)
  1713. bb_error_msg("history[%d]:'%s'", i, state->history[i]);
  1714. bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
  1715. #endif
  1716. /* Print out the command prompt, optionally ask where cursor is */
  1717. parse_and_put_prompt(prompt);
  1718. ask_terminal();
  1719. read_key_buffer[0] = 0;
  1720. while (1) {
  1721. /*
  1722. * The emacs and vi modes share much of the code in the big
  1723. * command loop. Commands entered when in vi's command mode
  1724. * (aka "escape mode") get an extra bit added to distinguish
  1725. * them - this keeps them from being self-inserted. This
  1726. * clutters the big switch a bit, but keeps all the code
  1727. * in one place.
  1728. */
  1729. enum {
  1730. VI_CMDMODE_BIT = 0x40000000,
  1731. /* 0x80000000 bit flags KEYCODE_xxx */
  1732. };
  1733. int32_t ic, ic_raw;
  1734. fflush_all();
  1735. ic = ic_raw = lineedit_read_key(read_key_buffer);
  1736. #if ENABLE_FEATURE_EDITING_VI
  1737. newdelflag = 1;
  1738. if (vi_cmdmode) {
  1739. /* btw, since KEYCODE_xxx are all < 0, this doesn't
  1740. * change ic if it contains one of them: */
  1741. ic |= VI_CMDMODE_BIT;
  1742. }
  1743. #endif
  1744. switch (ic) {
  1745. case '\n':
  1746. case '\r':
  1747. vi_case('\n'|VI_CMDMODE_BIT:)
  1748. vi_case('\r'|VI_CMDMODE_BIT:)
  1749. /* Enter */
  1750. goto_new_line();
  1751. break_out = 1;
  1752. break;
  1753. case CTRL('A'):
  1754. vi_case('0'|VI_CMDMODE_BIT:)
  1755. /* Control-a -- Beginning of line */
  1756. input_backward(cursor);
  1757. break;
  1758. case CTRL('B'):
  1759. vi_case('h'|VI_CMDMODE_BIT:)
  1760. vi_case('\b'|VI_CMDMODE_BIT:) /* ^H */
  1761. vi_case('\x7f'|VI_CMDMODE_BIT:) /* DEL */
  1762. input_backward(1); /* Move back one character */
  1763. break;
  1764. case CTRL('E'):
  1765. vi_case('$'|VI_CMDMODE_BIT:)
  1766. /* Control-e -- End of line */
  1767. input_end();
  1768. break;
  1769. case CTRL('F'):
  1770. vi_case('l'|VI_CMDMODE_BIT:)
  1771. vi_case(' '|VI_CMDMODE_BIT:)
  1772. input_forward(); /* Move forward one character */
  1773. break;
  1774. case '\b': /* ^H */
  1775. case '\x7f': /* DEL */
  1776. if (!isrtl_str())
  1777. input_backspace();
  1778. else
  1779. input_delete(0);
  1780. break;
  1781. case KEYCODE_DELETE:
  1782. if (!isrtl_str())
  1783. input_delete(0);
  1784. else
  1785. input_backspace();
  1786. break;
  1787. #if ENABLE_FEATURE_TAB_COMPLETION
  1788. case '\t':
  1789. input_tab(&lastWasTab);
  1790. break;
  1791. #endif
  1792. case CTRL('K'):
  1793. /* Control-k -- clear to end of line */
  1794. command_ps[cursor] = BB_NUL;
  1795. command_len = cursor;
  1796. printf("\033[J");
  1797. break;
  1798. case CTRL('L'):
  1799. vi_case(CTRL('L')|VI_CMDMODE_BIT:)
  1800. /* Control-l -- clear screen */
  1801. printf("\033[H");
  1802. redraw(0, command_len - cursor);
  1803. break;
  1804. #if MAX_HISTORY > 0
  1805. case CTRL('N'):
  1806. vi_case(CTRL('N')|VI_CMDMODE_BIT:)
  1807. vi_case('j'|VI_CMDMODE_BIT:)
  1808. /* Control-n -- Get next command in history */
  1809. if (get_next_history())
  1810. goto rewrite_line;
  1811. break;
  1812. case CTRL('P'):
  1813. vi_case(CTRL('P')|VI_CMDMODE_BIT:)
  1814. vi_case('k'|VI_CMDMODE_BIT:)
  1815. /* Control-p -- Get previous command from history */
  1816. if (get_previous_history())
  1817. goto rewrite_line;
  1818. break;
  1819. #endif
  1820. case CTRL('U'):
  1821. vi_case(CTRL('U')|VI_CMDMODE_BIT:)
  1822. /* Control-U -- Clear line before cursor */
  1823. if (cursor) {
  1824. command_len -= cursor;
  1825. memmove(command_ps, command_ps + cursor,
  1826. (command_len + 1) * sizeof(command_ps[0]));
  1827. redraw(cmdedit_y, command_len);
  1828. }
  1829. break;
  1830. case CTRL('W'):
  1831. vi_case(CTRL('W')|VI_CMDMODE_BIT:)
  1832. /* Control-W -- Remove the last word */
  1833. while (cursor > 0 && BB_isspace(command_ps[cursor-1]))
  1834. input_backspace();
  1835. while (cursor > 0 && !BB_isspace(command_ps[cursor-1]))
  1836. input_backspace();
  1837. break;
  1838. #if ENABLE_FEATURE_EDITING_VI
  1839. case 'i'|VI_CMDMODE_BIT:
  1840. vi_cmdmode = 0;
  1841. break;
  1842. case 'I'|VI_CMDMODE_BIT:
  1843. input_backward(cursor);
  1844. vi_cmdmode = 0;
  1845. break;
  1846. case 'a'|VI_CMDMODE_BIT:
  1847. input_forward();
  1848. vi_cmdmode = 0;
  1849. break;
  1850. case 'A'|VI_CMDMODE_BIT:
  1851. input_end();
  1852. vi_cmdmode = 0;
  1853. break;
  1854. case 'x'|VI_CMDMODE_BIT:
  1855. input_delete(1);
  1856. break;
  1857. case 'X'|VI_CMDMODE_BIT:
  1858. if (cursor > 0) {
  1859. input_backward(1);
  1860. input_delete(1);
  1861. }
  1862. break;
  1863. case 'W'|VI_CMDMODE_BIT:
  1864. vi_Word_motion(1);
  1865. break;
  1866. case 'w'|VI_CMDMODE_BIT:
  1867. vi_word_motion(1);
  1868. break;
  1869. case 'E'|VI_CMDMODE_BIT:
  1870. vi_End_motion();
  1871. break;
  1872. case 'e'|VI_CMDMODE_BIT:
  1873. vi_end_motion();
  1874. break;
  1875. case 'B'|VI_CMDMODE_BIT:
  1876. vi_Back_motion();
  1877. break;
  1878. case 'b'|VI_CMDMODE_BIT:
  1879. vi_back_motion();
  1880. break;
  1881. case 'C'|VI_CMDMODE_BIT:
  1882. vi_cmdmode = 0;
  1883. /* fall through */
  1884. case 'D'|VI_CMDMODE_BIT:
  1885. goto clear_to_eol;
  1886. case 'c'|VI_CMDMODE_BIT:
  1887. vi_cmdmode = 0;
  1888. /* fall through */
  1889. case 'd'|VI_CMDMODE_BIT: {
  1890. int nc, sc;
  1891. ic = lineedit_read_key(read_key_buffer);
  1892. if (errno) /* error */
  1893. goto prepare_to_die;
  1894. if (ic == ic_raw) { /* "cc", "dd" */
  1895. input_backward(cursor);
  1896. goto clear_to_eol;
  1897. break;
  1898. }
  1899. sc = cursor;
  1900. switch (ic) {
  1901. case 'w':
  1902. case 'W':
  1903. case 'e':
  1904. case 'E':
  1905. switch (ic) {
  1906. case 'w': /* "dw", "cw" */
  1907. vi_word_motion(vi_cmdmode);
  1908. break;
  1909. case 'W': /* 'dW', 'cW' */
  1910. vi_Word_motion(vi_cmdmode);
  1911. break;
  1912. case 'e': /* 'de', 'ce' */
  1913. vi_end_motion();
  1914. input_forward();
  1915. break;
  1916. case 'E': /* 'dE', 'cE' */
  1917. vi_End_motion();
  1918. input_forward();
  1919. break;
  1920. }
  1921. nc = cursor;
  1922. input_backward(cursor - sc);
  1923. while (nc-- > cursor)
  1924. input_delete(1);
  1925. break;
  1926. case 'b': /* "db", "cb" */
  1927. case 'B': /* implemented as B */
  1928. if (ic == 'b')
  1929. vi_back_motion();
  1930. else
  1931. vi_Back_motion();
  1932. while (sc-- > cursor)
  1933. input_delete(1);
  1934. break;
  1935. case ' ': /* "d ", "c " */
  1936. input_delete(1);
  1937. break;
  1938. case '$': /* "d$", "c$" */
  1939. clear_to_eol:
  1940. while (cursor < command_len)
  1941. input_delete(1);
  1942. break;
  1943. }
  1944. break;
  1945. }
  1946. case 'p'|VI_CMDMODE_BIT:
  1947. input_forward();
  1948. /* fallthrough */
  1949. case 'P'|VI_CMDMODE_BIT:
  1950. put();
  1951. break;
  1952. case 'r'|VI_CMDMODE_BIT:
  1953. //FIXME: unicode case?
  1954. ic = lineedit_read_key(read_key_buffer);
  1955. if (errno) /* error */
  1956. goto prepare_to_die;
  1957. if (ic < ' ' || ic > 255) {
  1958. beep();
  1959. } else {
  1960. command_ps[cursor] = ic;
  1961. bb_putchar(ic);
  1962. bb_putchar('\b');
  1963. }
  1964. break;
  1965. case '\x1b': /* ESC */
  1966. if (state->flags & VI_MODE) {
  1967. /* insert mode --> command mode */
  1968. vi_cmdmode = 1;
  1969. input_backward(1);
  1970. }
  1971. break;
  1972. #endif /* FEATURE_COMMAND_EDITING_VI */
  1973. #if MAX_HISTORY > 0
  1974. case KEYCODE_UP:
  1975. if (get_previous_history())
  1976. goto rewrite_line;
  1977. beep();
  1978. break;
  1979. case KEYCODE_DOWN:
  1980. if (!get_next_history())
  1981. break;
  1982. rewrite_line:
  1983. /* Rewrite the line with the selected history item */
  1984. /* change command */
  1985. command_len = load_string(state->history[state->cur_history] ?
  1986. state->history[state->cur_history] : "", maxsize);
  1987. /* redraw and go to eol (bol, in vi) */
  1988. redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
  1989. break;
  1990. #endif
  1991. case KEYCODE_RIGHT:
  1992. input_forward();
  1993. break;
  1994. case KEYCODE_LEFT:
  1995. input_backward(1);
  1996. break;
  1997. case KEYCODE_CTRL_LEFT:
  1998. ctrl_left();
  1999. break;
  2000. case KEYCODE_CTRL_RIGHT:
  2001. ctrl_right();
  2002. break;
  2003. case KEYCODE_HOME:
  2004. input_backward(cursor);
  2005. break;
  2006. case KEYCODE_END:
  2007. input_end();
  2008. break;
  2009. default:
  2010. if (initial_settings.c_cc[VINTR] != 0
  2011. && ic_raw == initial_settings.c_cc[VINTR]
  2012. ) {
  2013. /* Ctrl-C (usually) - stop gathering input */
  2014. goto_new_line();
  2015. command_len = 0;
  2016. break_out = -1; /* "do not append '\n'" */
  2017. break;
  2018. }
  2019. if (initial_settings.c_cc[VEOF] != 0
  2020. && ic_raw == initial_settings.c_cc[VEOF]
  2021. ) {
  2022. /* Ctrl-D (usually) - delete one character,
  2023. * or exit if len=0 and no chars to delete */
  2024. if (command_len == 0) {
  2025. errno = 0;
  2026. #if ENABLE_FEATURE_EDITING_VI
  2027. prepare_to_die:
  2028. #endif
  2029. break_out = command_len = -1;
  2030. break;
  2031. }
  2032. input_delete(0);
  2033. break;
  2034. }
  2035. // /* Control-V -- force insert of next char */
  2036. // if (c == CTRL('V')) {
  2037. // if (safe_read(STDIN_FILENO, &c, 1) < 1)
  2038. // goto prepare_to_die;
  2039. // if (c == 0) {
  2040. // beep();
  2041. // break;
  2042. // }
  2043. // }
  2044. if (ic < ' '
  2045. || (!ENABLE_UNICODE_SUPPORT && ic >= 256)
  2046. || (ENABLE_UNICODE_SUPPORT && ic >= VI_CMDMODE_BIT)
  2047. ) {
  2048. /* If VI_CMDMODE_BIT is set, ic is >= 256
  2049. * and vi mode ignores unexpected chars.
  2050. * Otherwise, we are here if ic is a
  2051. * control char or an unhandled ESC sequence,
  2052. * which is also ignored.
  2053. */
  2054. break;
  2055. }
  2056. if ((int)command_len >= (maxsize - 2)) {
  2057. /* Not enough space for the char and EOL */
  2058. break;
  2059. }
  2060. command_len++;
  2061. if (cursor == (command_len - 1)) {
  2062. /* We are at the end, append */
  2063. command_ps[cursor] = ic;
  2064. command_ps[cursor + 1] = BB_NUL;
  2065. cmdedit_set_out_char(' ');
  2066. if (unicode_bidi_isrtl(ic))
  2067. input_backward(1);
  2068. } else {
  2069. /* In the middle, insert */
  2070. int sc = cursor;
  2071. memmove(command_ps + sc + 1, command_ps + sc,
  2072. (command_len - sc) * sizeof(command_ps[0]));
  2073. command_ps[sc] = ic;
  2074. /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */
  2075. if (!isrtl_str())
  2076. sc++; /* no */
  2077. /* rewrite from cursor */
  2078. input_end();
  2079. /* to prev x pos + 1 */
  2080. input_backward(cursor - sc);
  2081. }
  2082. break;
  2083. } /* switch (ic) */
  2084. if (break_out)
  2085. break;
  2086. #if ENABLE_FEATURE_TAB_COMPLETION
  2087. if (ic_raw != '\t')
  2088. lastWasTab = FALSE;
  2089. #endif
  2090. } /* while (1) */
  2091. #if ENABLE_FEATURE_EDITING_ASK_TERMINAL
  2092. if (S.sent_ESC_br6n) {
  2093. /* "sleep 1; busybox ash" + hold [Enter] to trigger.
  2094. * We sent "ESC [ 6 n", but got '\n' first, and
  2095. * KEYCODE_CURSOR_POS response is now buffered from terminal.
  2096. * It's bad already and not much can be done with it
  2097. * (it _will_ be visible for the next process to read stdin),
  2098. * but without this delay it even shows up on the screen
  2099. * as garbage because we restore echo settings with tcsetattr
  2100. * before it comes in. UGLY!
  2101. */
  2102. usleep(20*1000);
  2103. }
  2104. #endif
  2105. /* Stop bug catching using "command_must_not_be_used" trick */
  2106. #undef command
  2107. #if ENABLE_UNICODE_SUPPORT
  2108. command[0] = '\0';
  2109. if (command_len > 0)
  2110. command_len = save_string(command, maxsize - 1);
  2111. free(command_ps);
  2112. #endif
  2113. if (command_len > 0)
  2114. remember_in_history(command);
  2115. if (break_out > 0) {
  2116. command[command_len++] = '\n';
  2117. command[command_len] = '\0';
  2118. }
  2119. #if ENABLE_FEATURE_TAB_COMPLETION
  2120. free_tab_completion_data();
  2121. #endif
  2122. /* restore initial_settings */
  2123. tcsetattr_stdin_TCSANOW(&initial_settings);
  2124. /* restore SIGWINCH handler */
  2125. signal(SIGWINCH, previous_SIGWINCH_handler);
  2126. fflush_all();
  2127. len = command_len;
  2128. DEINIT_S();
  2129. return len; /* can't return command_len, DEINIT_S() destroys it */
  2130. }
  2131. #else
  2132. #undef read_line_input
  2133. int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
  2134. {
  2135. fputs(prompt, stdout);
  2136. fflush_all();
  2137. fgets(command, maxsize, stdin);
  2138. return strlen(command);
  2139. }
  2140. #endif /* FEATURE_EDITING */
  2141. /*
  2142. * Testing
  2143. */
  2144. #ifdef TEST
  2145. #include <locale.h>
  2146. const char *applet_name = "debug stuff usage";
  2147. int main(int argc, char **argv)
  2148. {
  2149. char buff[MAX_LINELEN];
  2150. char *prompt =
  2151. #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
  2152. "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:"
  2153. "\\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] "
  2154. "\\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]";
  2155. #else
  2156. "% ";
  2157. #endif
  2158. #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
  2159. setlocale(LC_ALL, "");
  2160. #endif
  2161. while (1) {
  2162. int l;
  2163. l = read_line_input(prompt, buff);
  2164. if (l <= 0 || buff[l-1] != '\n')
  2165. break;
  2166. buff[l-1] = 0;
  2167. printf("*** read_line_input() returned line =%s=\n", buff);
  2168. }
  2169. printf("*** read_line_input() detect ^D\n");
  2170. return 0;
  2171. }
  2172. #endif /* TEST */