/* finds and print all occurencies of commands from the history which * start with <cmd> * Returns the number of found entries on success, * and 0 if no such entry exists * * Peter Weilbacher 28Jun2004 */ int history_find_all(char *cmd) { int len; int found; int number = 0; /* each found entry increases this */ /* quote removal, copied from non-readline version */ if (*cmd == '"') cmd++; if (!*cmd) return 0; len = strlen(cmd); if (cmd[len - 1] == '"') cmd[--len] = 0; if (!*cmd) return 0; /* printf ("searching for all occurrences of '%s'\n", cmd); */ /* Output matching history entries in chronological order (not backwards * so we have to start at the beginning of the history list. */ history_set_pos(0); do { found = history_search_prefix(cmd, 1); /* Anchored backward search for prefix */ if (found == 0) { number++; printf("%5i %s\n", where_history() + history_base, current_history()->line); /* go one step back or you find always the same entry. */ if (!history_set_pos(where_history() + 1)) break; /* finished if stepping didn't work */ } /* (found == 0) */ } while (found > -1); return number; }
/* Search for a line in the history containing STRING. If DIR is < 0, the search is backwards through previous entries, else through subsequent entries. */ static void noninc_dosearch (char *string, int dir) { int oldpos, pos; HIST_ENTRY *entry; if (string == 0 || *string == '\0' || noninc_history_pos < 0) { DING (); return; } pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); if (pos == -1) { /* Search failed, current history position unchanged. */ maybe_unsave_line (); rl_clear_message (); rl_point = 0; DING (); return; } noninc_history_pos = pos; oldpos = where_history (); history_set_pos (noninc_history_pos); entry = current_history (); #if defined (VI_MODE) if (rl_editing_mode != vi_mode) #endif history_set_pos (oldpos); { int line_len; line_len = strlen (entry->line); if (line_len >= rl_line_buffer_len) rl_extend_line_buffer (line_len); strcpy (rl_line_buffer, entry->line); } rl_undo_list = (UNDO_LIST *)entry->data; rl_end = strlen (rl_line_buffer); rl_point = 0; rl_clear_message (); if (saved_line_for_history) _rl_free_history_entry (saved_line_for_history); saved_line_for_history = (HIST_ENTRY *)NULL; }
/* finds and print all occurencies of commands from the history which * start with <cmd> * Returns the number of found entries on success, * and 0 if no such entry exists * * Peter Weilbacher 28Jun2004 */ int history_find_all(char *cmd) { int len; int found; int number = 0; /* each found entry increases this */ /* quote removal, copied from non-readline version */ if (*cmd == '"') cmd++; if (!*cmd) return 0; len = strlen(cmd); if (cmd[len - 1] == '"') cmd[--len] = 0; if (!*cmd) return 0; /* printf ("searching for all occurrences of '%s'\n", cmd); */ /* Output matching history entries in chronological order (not backwards * so we have to start at the beginning of the history list. */ #if defined(HAVE_LIBREADLINE) found = history_set_pos(0); if (found == -1) { fprintf(stderr, "ERROR (history_find_all): could not rewind history\n"); return 0; } #else /* HAVE_LIBEDITLINE */ /* libedit's history_set_pos() does not work properly, so we manually go to oldest entry */ while (next_history()); #endif do { found = history_search_prefix(cmd, 1); /* Anchored backward search for prefix */ if (found == 0) { number++; #if defined(HAVE_LIBREADLINE) printf("%5i %s\n", where_history() + history_base, current_history()->line); /* go one step back or you find always the same entry. */ if (!history_set_pos(where_history() + 1)) break; /* finished if stepping didn't work */ #else /* HAVE_LIBEDITLINE */ /* libedit's history indices are reversed wrt GNU readline */ printf("%5i %s\n", history_length - where_history() + history_base, current_history()->line); /* go one step back or you find always the same entry. */ if (!previous_history()) break; /* finished if stepping didn't work */ #endif } /* (found == 0) */ } while (found > -1); return number; }
int cli_init(struct parser_state *_state) { const char *home; rl_readline_name = "nft"; rl_instream = stdin; rl_outstream = stdout; rl_callback_handler_install("nft> ", cli_complete); rl_attempted_completion_function = cli_completion; home = getenv("HOME"); if (home == NULL) home = ""; snprintf(histfile, sizeof(histfile), "%s/%s", home, CMDLINE_HISTFILE); read_history(histfile); history_set_pos(history_length); state = _state; scanner = scanner_init(state); while (!eof) rl_callback_read_char(); return 0; }
//------------------------------------------------------------------------------ static void load_history() { char buffer[1024]; get_history_file_name(buffer, sizeof(buffer)); read_history(buffer); history_set_pos(history_length); }
void edit_deinit(const char *history_file, int (*filter_cb)(void *ctx, const char *cmd)) { rl_callback_handler_remove(); readline_free_completions(); eloop_unregister_read_sock(STDIN_FILENO); if (history_file) { /* Save command history, excluding lines that may contain * passwords. */ HIST_ENTRY *h; history_set_pos(0); while ((h = current_history())) { char *p = h->line; while (*p == ' ' || *p == '\t') p++; if (filter_cb && filter_cb(edit_cb_ctx, p)) { h = remove_history(where_history()); if (h) { os_free(h->line); free(h->data); os_free(h); } else next_history(); } else next_history(); } write_history(history_file); } }
/* Search the history list for STRING starting at absolute history position POS. If STRING begins with `^', the search must match STRING at the beginning of a history line, otherwise a full substring match is performed for STRING. DIR < 0 means to search backwards through the history list, DIR >= 0 means to search forward. */ static int noninc_search_from_pos (char *string, int pos, int dir) { int ret, old; old = where_history (); history_set_pos (pos); if (*string == '^') ret = history_search_prefix (string + 1, dir); else ret = history_search (string, dir); if (ret != -1) ret = where_history (); history_set_pos (old); return (ret); }
/* Reading and Writing the librline context. {{{*/ int rline_read_history(struct rline *rline, const char *file) { if (!rline) return -1; using_history(); read_history(file); history_set_pos(history_length); return 0; }
int _el_display_last_hist() { if (where_history() < (history_length() - 1)) { if (!_el_w2mb(_el_line_buffer, &rl_line_buffer)) { return -1; } replace_history_entry(where_history(), rl_line_buffer, NULL); history_set_pos(history_length() - 1); _el_display_history(); } return 0; }
/* * Reverse the above encoding */ static void decode_history(void) { HIST_ENTRY *cur_hist; char *cur_ptr; history_set_pos(0); for (cur_hist = current_history(); cur_hist; cur_hist = next_history()) { /* some platforms declare HIST_ENTRY.line as const char * */ for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++) if (*cur_ptr == NL_IN_HISTORY) *cur_ptr = '\n'; } }
int nxtcmd (char *cmd, char *prompt) { int i, len, past=0, cnt=0; printf ("%s ",prompt); /* this is actually redirected by console() */ plen = strlen(prompt)+1; past = cnt = 0; if ( x11_initialized ) { got_grads_cmd = 0; /* fresh as new */ while (1) { console(); /* console manager: handles stdio */ if(got_grads_cmd) { strcpy(cmd,grads_cmd); got_grads_cmd = 0; /* fresh as new */ len = strlen(cmd); #if !defined(STNDALN) if(len>0) { add_history(cmd); /* add to the history list */ history_set_pos(history_length); } #endif return(len); } } } else { /* do as in regular grads */ while (1) { *cmd = getchar(); if (*cmd == EOF) { return(-1); } if (*cmd == '\n') { cmd++; *cmd = '\0'; return(cnt); } if (past || *cmd != ' ') { cmd++; cnt++; past = 1; } } } }
static int down_callback(int count, int key) { reset_indent(); int j = line_end(rl_point); if (j < rl_end) { int i = line_start(rl_point); if (i == 0) rl_point += prompt_length; rl_point += j - i + 1; int k = line_end(j+1); if (rl_point > k) rl_point = k; return 0; } else { if (last_hist_offset >= 0) { history_set_pos(last_hist_offset); last_hist_offset = -1; } return rl_get_next_history(count, key); } }
/* Process and free undo lists attached to each history entry prior to the current entry, inclusive, reverting each line to its saved state. This is destructive, and state about the current line is lost. This is not intended to be called while actively editing, and the current line is not assumed to have been added to the history list. */ void _rl_revert_all_lines (void) { int hpos; HIST_ENTRY *entry; UNDO_LIST *ul, *saved_undo_list; char *lbuf; lbuf = savestring (rl_line_buffer); saved_undo_list = rl_undo_list; hpos = where_history (); entry = (hpos == history_length) ? previous_history () : current_history (); while (entry) { if (ul = (UNDO_LIST *)entry->data) { if (ul == saved_undo_list) saved_undo_list = 0; /* Set up rl_line_buffer and other variables from history entry */ rl_replace_from_history (entry, 0); /* entry->line is now current */ entry->data = 0; /* entry->data is now current undo list */ /* Undo all changes to this history entry */ while (rl_undo_list) rl_do_undo (); /* And copy the reverted line back to the history entry, preserving the timestamp. */ FREE (entry->line); entry->line = savestring (rl_line_buffer); } entry = previous_history (); } /* Restore history state */ rl_undo_list = saved_undo_list; /* may have been set to null */ history_set_pos (hpos); /* reset the line buffer */ rl_replace_line (lbuf, 0); _rl_set_the_line (); /* and clean up */ xfree (lbuf); }
readline_constructor_impl::impl::impl( readline* parent, boost::asio::io_service& io_service, boost::function<void(std::string const&, readline&)> const& command_handler, boost::function<void(readline&)> const& eof_handler, std::string const& prompt, boost::filesystem::path const& history_file, boost::function<bool(std::string const&)> const& history_filter ) : parent_(parent), io_service_(io_service), command_handler_(command_handler), eof_handler_(eof_handler), prompt_(prompt), history_file_(history_file), history_filter_(history_filter), stdin_reader_(io_service, 0), // Bind to stdin redisplay_timer_(io_service) { if (current_readline) { throw std::logic_error("Can't create multiple relasio::readline objects"); } current_readline = this; if (!history_file_.empty() && boost::filesystem::exists(history_file_)) { if (!boost::filesystem::is_directory(history_file_)) { if (0 == read_history(history_file_.c_str())) { if (0 == history_set_pos(history_length)) { throw relasio_error("error setting history position\n"); } if (history_length > 0) { // Set up last_line_ HIST_ENTRY* last = history_get(history_length); if (last) last_line_ = last->line; } } else { throw relasio_error("error reading history\n"); } } } rl_callback_handler_install( prompt_.c_str(), relasio_line_callback_handler ); wait_for_chars(); }
int shell(void) { fd_set readset; FD_ZERO(&g_context.readsave); if(g_verbose) { fprintf(stderr, "Opening connection to %s port %d\n", g_context.args.ip, g_context.args.port); } if((g_context.sock = connect_to(g_context.args.ip, g_context.args.port)) < 0) { return 1; } if(g_context.args.notty == 0) { if((g_context.outsock = connect_to(g_context.args.ip, g_context.args.port+2)) < 0) { fprintf(stderr, "Could not connect to stdout channel\n"); } if((g_context.errsock = connect_to(g_context.args.ip, g_context.args.port+3)) < 0) { fprintf(stderr, "Could not connect to stderr channel\n"); } } /* if((g_context.fssock == connect_to(g_context.args.ip, g_context.args.port+8)) < 0) { fprintf(stderr, "Could not connect to fs admin channel\n"); } */ if(!g_context.args.script) { init_readline(); read_history(g_context.history_file); history_set_pos(history_length); FD_SET(STDIN_FILENO, &g_context.readsave); } /* Change to the current directory, should return our path */ execute_line("cd ."); while(!g_context.exit) { int ret; readset = g_context.readsave; ret = select(FD_SETSIZE, &readset, NULL, NULL, NULL); if(ret < 0) { if(errno == EINTR) { continue; } perror("select"); break; } else if(ret == 0) { continue; } else { if(!g_context.args.script) { if(FD_ISSET(STDIN_FILENO, &readset)) { rl_callback_read_char(); } } if(FD_ISSET(g_context.sock, &readset)) { /* Do read */ if(read_socket(g_context.sock) < 0) { close(g_context.sock); g_context.sock = -1; break; } } if((g_context.outsock >= 0) && FD_ISSET(g_context.outsock, &readset)) { if(read_outsocket(g_context.outsock) < 0) { FD_CLR(g_context.outsock, &g_context.readsave); close(g_context.outsock); g_context.outsock = -1; } } if((g_context.errsock >= 0) && FD_ISSET(g_context.errsock, &readset)) { if(read_errsocket(g_context.errsock) < 0) { FD_CLR(g_context.errsock, &g_context.readsave); close(g_context.errsock); g_context.errsock = -1; } } if((g_context.fssock >= 0) && FD_ISSET(g_context.fssock, &readset)) { if(read_fssocket(g_context.fssock) < 0) { FD_CLR(g_context.fssock, &g_context.readsave); close(g_context.fssock); g_context.fssock = -1; } } } } if(!g_context.args.script) { write_history(g_context.history_file); rl_callback_handler_remove(); } return 0; }
static void wpa_cli_reconnect(void) { wpa_cli_close_connection(); ctrl_conn = wpa_cli_open_connection(ctrl_ifname); if (ctrl_conn) { printf("Connection to wpa_supplicant re-established\n"); #ifdef ANDROID if (wpa_ctrl_attach(monitor_conn) == 0) { #else if (wpa_ctrl_attach(ctrl_conn) == 0) { #endif wpa_cli_attached = 1; } else { printf("Warning: Failed to attach to " "wpa_supplicant.\n"); } } } static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, int action_monitor) { int first = 1; #ifdef ANDROID if (ctrl == NULL) { #else if (ctrl_conn == NULL) { #endif wpa_cli_reconnect(); return; } while (wpa_ctrl_pending(ctrl) > 0) { char buf[256]; size_t len = sizeof(buf) - 1; if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { buf[len] = '\0'; if (action_monitor) wpa_cli_action_process(buf); else { if (in_read && first) printf("\n"); first = 0; printf("%s\n", buf); } } else { printf("Could not read pending message.\n"); break; } } if (wpa_ctrl_pending(ctrl) < 0) { printf("Connection to wpa_supplicant lost - trying to " "reconnect\n"); wpa_cli_reconnect(); } } #ifdef CONFIG_READLINE static char * wpa_cli_cmd_gen(const char *text, int state) { static int i, len; const char *cmd; if (state == 0) { i = 0; len = os_strlen(text); } while ((cmd = wpa_cli_commands[i].cmd)) { i++; if (os_strncasecmp(cmd, text, len) == 0) return os_strdup(cmd); } return NULL; } static char * wpa_cli_dummy_gen(const char *text, int state) { return NULL; } static char ** wpa_cli_completion(const char *text, int start, int end) { return rl_completion_matches(text, start == 0 ? wpa_cli_cmd_gen : wpa_cli_dummy_gen); } #endif /* CONFIG_READLINE */ static void wpa_cli_interactive(void) { #define max_args 10 char cmdbuf[256], *cmd, *argv[max_args], *pos; int argc; #ifdef CONFIG_READLINE char *home, *hfile = NULL; #endif /* CONFIG_READLINE */ printf("\nInteractive mode\n\n"); #ifdef CONFIG_READLINE rl_attempted_completion_function = wpa_cli_completion; home = getenv("HOME"); if (home) { const char *fname = ".wpa_cli_history"; int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; hfile = os_malloc(hfile_len); if (hfile) { int res; res = os_snprintf(hfile, hfile_len, "%s/%s", home, fname); if (res >= 0 && res < hfile_len) { hfile[hfile_len - 1] = '\0'; read_history(hfile); stifle_history(100); } } } #endif /* CONFIG_READLINE */ do { #ifdef ANDROID wpa_cli_recv_pending(monitor_conn, 0, 0); #else wpa_cli_recv_pending(ctrl_conn, 0, 0); #endif #ifndef CONFIG_NATIVE_WINDOWS alarm(ping_interval); #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef CONFIG_READLINE cmd = readline("> "); if (cmd && *cmd) { HIST_ENTRY *h; while (next_history()) ; h = previous_history(); if (h == NULL || os_strcmp(cmd, h->line) != 0) add_history(cmd); next_history(); } #else /* CONFIG_READLINE */ printf("> "); cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); #endif /* CONFIG_READLINE */ #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ if (cmd == NULL) break; #ifdef ANDROID wpa_cli_recv_pending(monitor_conn, 0, 0); #else wpa_cli_recv_pending(ctrl_conn, 0, 0); #endif pos = cmd; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } argc = 0; pos = cmd; for (;;) { while (*pos == ' ') pos++; if (*pos == '\0') break; argv[argc] = pos; argc++; if (argc == max_args) break; if (*pos == '"') { char *pos2 = os_strrchr(pos, '"'); if (pos2) pos = pos2 + 1; } while (*pos != '\0' && *pos != ' ') pos++; if (*pos == ' ') *pos++ = '\0'; } if (argc) wpa_request(ctrl_conn, argc, argv); if (cmd != cmdbuf) os_free(cmd); } while (!wpa_cli_quit); #ifdef CONFIG_READLINE if (hfile) { /* Save command history, excluding lines that may contain * passwords. */ HIST_ENTRY *h; history_set_pos(0); while ((h = current_history())) { char *p = h->line; while (*p == ' ' || *p == '\t') p++; if (cmd_has_sensitive_data(p)) { h = remove_history(where_history()); if (h) { os_free(h->line); os_free(h->data); os_free(h); } else next_history(); } else next_history(); } write_history(hfile); os_free(hfile); } #endif /* CONFIG_READLINE */ }
static int handle_hotkey2(int UNUSED(count), int hotkey, int ignore_history) { char *prefix, *postfix, *history, *histpos_as_string, *executing_keyseq; char *new_prefix, *new_postfix, *new_history, *new_histpos_as_string, *message; char *filter_food, *filtered, **fragments, *new_rl_line_buffer; int length, new_histpos; unsigned long int hash; static const unsigned int MAX_HISTPOS_DIGITS = 6; /* one million history items should suffice */ #ifdef HAVE_RL_EXECUTING_KEYSEQ /* i.e. if readline version is >= 6.3 */ executing_keyseq = mysavestring(rl_executing_keyseq); #else executing_keyseq = mysavestring("?"); *executing_keyseq = hotkey; /* The filter will only get the *last* byte of the key sequence that triggered rl_handle_hotkey */ #endif DPRINTF3(DEBUG_READLINE, "hotkey press (ignore_history == %d): %x (%s)", ignore_history, hotkey, mangle_string_for_debug_log(executing_keyseq, MANGLE_LENGTH)); if (hotkey == '\t') /* this would go horribly wrong with all the splitting on '\t' going on.... @@@ or pass key as a string e.g. "009" */ myerror(FATAL | NOERRNO, "Sorry, you cannot use TAB as an hotkey in rlwrap"); prefix = mysavestring(rl_line_buffer); prefix[rl_point] = '\0'; /* chop off just before cursor */ postfix = mysavestring(rl_line_buffer + rl_point); if (ignore_history) { histpos_as_string = mysavestring("0"); history = mysavestring(""); } else { histpos_as_string = as_string(where_history()); assert(strlen(histpos_as_string) <= MAX_HISTPOS_DIGITS); history = entire_history_as_one_string(); hash = hash_multiple(2, history, histpos_as_string); } /* filter_food = key + tab + prefix + tab + postfix + tab + history + tab + histpos + '\0' */ length = strlen(rl_line_buffer) + strlen(history) + MAX_HISTPOS_DIGITS + 5; filter_food = mymalloc(length); sprintf(filter_food, "%s\t%s\t%s\t%s\t%s", executing_keyseq, prefix, postfix, history, histpos_as_string); /* this is the format that the filter expects */ /* let the filter filter ...! */ filtered= pass_through_filter(TAG_HOTKEY, filter_food); /* OK, we now have to read back everything. There should be exactly 5 TAB-separated components*/ fragments = split_on_single_char(filtered, '\t', 5); message = fragments[0]; new_prefix = fragments[1]; new_postfix = fragments[2]; new_history = fragments[3]; new_histpos_as_string = fragments[4]; if (!ignore_history && hash_multiple(2, new_history, new_histpos_as_string) != hash) { /* history has been rewritten */ char **linep, **history_lines = split_on_single_char(new_history, '\n', 0); DPRINTF3(DEBUG_READLINE, "hash=%lx, new_history is %d bytes long, histpos <%s>", hash, (int) strlen(new_history), new_histpos_as_string); clear_history(); for (linep = history_lines; *linep; linep++) add_history(*linep); new_histpos = my_atoi(new_histpos_as_string); history_set_pos(new_histpos); free_splitlist(history_lines); } new_rl_line_buffer = add2strings(new_prefix, new_postfix); if ( (length = strlen(new_rl_line_buffer)) > 0 && new_rl_line_buffer[length - 1] == '\n') { new_rl_line_buffer[length - 1] = '\0'; rl_done = TRUE; return_key = (char) '\n'; assert(strchr(new_rl_line_buffer, '\n') == NULL); } rl_delete_text(0, strlen(rl_line_buffer)); rl_point = 0; rl_insert_text(new_rl_line_buffer); rl_point = strlen(new_rl_line_buffer); if (*message && *message != hotkey) { /* if message has been set (i.e. != hotkey) , and isn't empty: */ message = append_and_free_old(mysavestring(message), " "); /* put space (for readability) between the message and the input line .. */ message_in_echo_area(message); /* .. then write it to echo area */ } clear_line(); rl_on_new_line(); rl_redisplay(); free_splitlist(fragments); /* this will free all the fragments (and the list itself) in one go */ free_multiple(prefix, postfix, filter_food, executing_keyseq, filtered, new_rl_line_buffer, history, histpos_as_string, FMEND); return 0; }
/* main readline function */ char *readline(const char *prompt) { wchar_t buf[_EL_CONSOLE_BUF_LEN]; char **array = NULL; char *ret_string = NULL; int start = 0; int end = 0; int compl_pos = -1; int n = 0; int index = 0; int len = 0; int line_len = 0; int old_width = 0; int width = 0; UINT32 ctrl = 0; UINT32 special = 0; COORD coord; DWORD count = 0; INPUT_RECORD irBuffer; CONSOLE_SCREEN_BUFFER_INFO sbInfo; static int piped_input_finished = FALSE; if (piped_input_finished) { return NULL; } _el_ctrl_c_pressed = FALSE; _el_line_buffer = NULL; _el_temp_print = NULL; _el_next_compl = NULL; rl_line_buffer = NULL; _el_file_name = NULL; _el_dir_name = NULL; _el_old_arg = NULL; _el_wide = NULL; _el_text = NULL; _el_text_mb = NULL; _el_compl_array = NULL; _el_completer_word_break_characters = NULL; rl_point = 0; rl_attempted_completion_over = 0; _el_compl_index = 0; _el_n_compl = 0; _el_h_in = NULL; _el_h_out = NULL; wcscpy_s(_el_basic_file_break_characters, _EL_MAX_FILE_BREAK_CHARACTERS, _EL_BASIC_FILE_BREAK_CHARACTERS); memset(&coord, 0, sizeof(COORD)); memset(buf, 0, _EL_CONSOLE_BUF_LEN * sizeof(wchar_t)); memset(&irBuffer, 0, sizeof(INPUT_RECORD)); /* allocate buffers */ _el_line_buffer_size = _EL_BUF_LEN + 1; _el_line_buffer = (wchar_t *)malloc(_el_line_buffer_size * sizeof(wchar_t)); if (!_el_mb2w((char *)rl_basic_word_break_characters, &_el_basic_word_break_characters)) { _el_clean_exit(); return NULL; } if (rl_completer_word_break_characters) { if (!_el_mb2w((char *)rl_completer_word_break_characters, &_el_completer_word_break_characters)) { _el_clean_exit(); return NULL; } } if (!(_el_line_buffer)) { _el_clean_exit(); return NULL; } memset(_el_line_buffer, 0, _el_line_buffer_size * sizeof(wchar_t)); rl_attempted_completion_over = 0; _el_print = (wchar_t *)malloc(_el_line_buffer_size * sizeof(wchar_t)); if (!(_el_print)) { _el_clean_exit(); return NULL; } memset(_el_print, 0, _el_line_buffer_size * sizeof(wchar_t)); rl_prompt = _strdup(prompt); if (!(rl_prompt)) { _el_clean_exit(); return NULL; } if (!_el_mb2w((char *)prompt, &_el_prompt)) { _el_clean_exit(); return NULL; } _el_prompt_len = (int)wcslen(_el_prompt); /* get I/O handles for current console */ _el_h_in = GetStdHandle(STD_INPUT_HANDLE); _el_h_out = GetStdHandle(STD_OUTPUT_HANDLE); if ((!(_el_h_in)) || (!(_el_h_out))) { _el_clean_exit(); return NULL; } /* set console modes */ _el_prev_in_cm_saved = GetConsoleMode(_el_h_in, &_el_prev_in_cm); _el_prev_out_cm_saved = GetConsoleMode(_el_h_out, &_el_prev_out_cm); SetConsoleMode(_el_h_in, ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE); SetConsoleMode(_el_h_out, ENABLE_PROCESSED_OUTPUT); SetConsoleCtrlHandler((PHANDLER_ROUTINE) _el_signal_handler, TRUE); rl_point = 0; while ((buf[0] != VK_RETURN) && (!_el_ctrl_c_pressed) && _el_line_buffer) { /* get screen buffer info from the current console */ if (!GetConsoleScreenBufferInfo(_el_h_out, &sbInfo)) { _el_clean_exit(); return NULL; } _el_temp_print_size = sbInfo.dwSize.X + 1; if (!(_el_temp_print = realloc(_el_temp_print, _el_temp_print_size * sizeof(wchar_t)))) { _el_clean_exit(); return NULL; } _el_temp_print[0] = _T('\0'); /* compute the current visible console width */ width = sbInfo.srWindow.Right - sbInfo.srWindow.Left + 1; /* if the user has changed the window size update the view */ if (old_width != width) { line_len = (int)wcslen(_el_line_buffer); sbInfo.dwCursorPosition.X = 0; if (old_width) { n = (_el_prompt_len + line_len - 1) / old_width; sbInfo.dwCursorPosition.Y -= n; coord.Y = sbInfo.dwCursorPosition.Y; } if (!SetConsoleCursorPosition(_el_h_out, sbInfo.dwCursorPosition)) { _el_clean_exit(); return NULL; } if (_el_print_string(_el_prompt)) { _el_clean_exit(); return NULL; } if (_el_set_cursor(_el_prompt_len)) { _el_clean_exit(); return NULL; } if (_el_print_string(_el_line_buffer)) { _el_clean_exit(); return NULL; } if (_el_set_cursor(line_len)) { _el_clean_exit(); return NULL; } if (old_width && (old_width < width)) { coord.X = 0; coord.Y += (_el_prompt_len + line_len - 1) / width + 1; FillConsoleOutputCharacter(_el_h_out, _T(' '), sbInfo.dwSize.X * (n + 2), coord, &count); } } old_width = width; /* wait for console events */ if (!PeekConsoleInput(_el_h_in, &irBuffer, 1, &count)) { /* Check we're possibly piped from another program. */ BOOL ret; char *pos, buf[8192]; DWORD to_read = sizeof(buf); /* Can't guarantee Unicode here, we don't control the data passed through the pipe. */ pos = buf; memset(pos, 0, sizeof(buf)); do { ret = ReadFile(_el_h_in, pos, to_read, &count, 0); pos += count; to_read -= count; } while (ret && to_read > 0); if (pos == buf) { _el_clean_exit(); return NULL; } else if (to_read > 0) { /* Tried to fill the buf, but there's nothing anymore. Force finish. */ piped_input_finished = TRUE; } buf[pos - buf] = '\0'; ret_string = _strdup(buf); _el_clean_exit(); return ret_string; } if (count) { if ((irBuffer.EventType == KEY_EVENT) && irBuffer.Event.KeyEvent.bKeyDown) { /* the user pressed a key */ ctrl = (irBuffer.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)); if (irBuffer.Event.KeyEvent.uChar.UnicodeChar == _T('\n')) { if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } buf[0] = VK_RETURN; continue; } if (irBuffer.Event.KeyEvent.uChar.UnicodeChar == _T('\0')) { /* if it is a special key, just remove it from the buffer */ if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } special = irBuffer.Event.KeyEvent.wVirtualKeyCode; /* parse the special key */ switch (special) { /* arrow left, arrow right HOME and END keys */ case VK_LEFT: case VK_RIGHT: case VK_HOME: case VK_END: if (_el_move_cursor(special, ctrl)) { _el_clean_exit(); return NULL; } break; /* arrow up: display previous history element (if any) after recording the current command line */ case VK_UP: if (_el_display_prev_hist()) { _el_clean_exit(); return NULL; } break; /* page up: display the first history element (if any) after recording the current command line */ case VK_PRIOR: if (_el_display_first_hist()) { _el_clean_exit(); return NULL; } break; /* arrow down: display next history element (if any) after recording the current command line */ case VK_DOWN: if (_el_display_next_hist()) { _el_clean_exit(); return NULL; } break; case VK_NEXT: /* page down: display last history element (if any) after recording the current command line */ if (_el_display_last_hist()) { _el_clean_exit(); return NULL; } break; /* delete char */ case VK_DELETE: if (rl_point != wcslen(_el_line_buffer)) { if (_el_delete_char(VK_DELETE, 1)) { _el_clean_exit(); return NULL; } _el_compl_index = 0; compl_pos = -1; } break; } } else { /* if it is a normal key, remove it from the buffer */ memset(buf, 0, _EL_CONSOLE_BUF_LEN * sizeof(wchar_t)); if (!ReadConsole(_el_h_in, buf, 1, &count, NULL)) { _el_clean_exit(); return NULL; } /* then parse it */ switch (buf[0]) { /* backspace */ case VK_BACK: if (rl_point) { _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_BACK, 1)) { _el_clean_exit(); return NULL; } } break; /* TAB: do completion */ case VK_TAB: if ((!array) || (rl_point != compl_pos)) { _el_free_array(array); index = 0; if (_el_text) { free(_el_text); _el_text = NULL; } if (!(_el_text = _el_get_compl_text(&start, &end))) { _el_clean_exit(); return NULL; } if (_el_old_arg) { _el_old_arg[0] = _T('\0'); } if (!_el_w2mb(_el_text, &_el_text_mb)) { _el_clean_exit(); return NULL; } if (!_el_w2mb(_el_line_buffer, &rl_line_buffer)) { _el_clean_exit(); return NULL; } array = (rl_attempted_completion_function ? rl_attempted_completion_function(_el_text_mb, start, end) : rl_completion_matches(_el_text_mb, (rl_completion_entry_function ? rl_completion_entry_function : rl_filename_completion_function))); if (!array) { _el_clean_exit(); return NULL; } } if (!array[index]) { index = 0; } if (array[index]) { if (!_el_mb2w(array[index], &_el_next_compl)) { _el_clean_exit(); return NULL; } len = 0; if (_el_old_arg) { len = (int)wcslen(_el_old_arg); #if 0 fwprintf(stderr, _T("VK_TAB) _el_old_arg = '%s', len = %d\n"), _el_old_arg, len); fflush(stderr); #endif } if (!len) { len = (int)wcslen(_el_text); } if (len) { if (_el_delete_char(VK_BACK, len)) { _el_clean_exit(); return NULL; } } len = (int)wcslen(_el_next_compl); if (!(_el_old_arg = realloc(_el_old_arg, (len + 1) * sizeof(wchar_t)))) { return NULL; } _el_old_arg[len] = _T('\0'); memcpy(_el_old_arg, _el_next_compl, len * sizeof(wchar_t)); line_len = (int)wcslen(_el_line_buffer); if (_el_insert_char(_el_next_compl, len)) { _el_clean_exit(); return NULL; } free(_el_next_compl); _el_next_compl = NULL; compl_pos = ((rl_point && (!wcschr(_el_completer_word_break_characters ? _el_completer_word_break_characters : _el_basic_word_break_characters, _el_line_buffer[rl_point - 1]))) ? rl_point : -1); ++index; } break; /* ENTER: move the cursor to end of line, then return to the caller program */ case VK_RETURN: if (_el_set_cursor((int)wcslen(_el_line_buffer) - rl_point)) { _el_clean_exit(); return NULL; } break; /* delete word */ case 0x17: /* CTRL + W */ if (ctrl) { if (!rl_point) { break; } n = 1; while (((rl_point - n) > 0) && (iswspace(_el_line_buffer[rl_point - n]))) { ++n; } while ((rl_point - n) && (!iswspace(_el_line_buffer[rl_point - n]))) { ++n; } if (rl_point - n) { --n; } _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_BACK, n)) { _el_clean_exit(); return NULL; } break; } /* delete until end of line */ case 0x0B: /* CTRL + K */ if (ctrl) { line_len = (int)wcslen(_el_line_buffer); if (rl_point < line_len) { _el_compl_index = 0; compl_pos = -1; if (_el_delete_char(VK_DELETE, line_len - rl_point)) { _el_clean_exit(); return NULL; } } break; } /* beginning-of-line */ case 0x01: /* CTRL + A */ if (_el_move_cursor(VK_HOME, 0)) { _el_clean_exit(); return NULL; } break; /* end-of-line */ case 0x05: /* CTRL + E */ if (_el_move_cursor(VK_END, 0)) { _el_clean_exit(); return NULL; } break; /* forward-char */ case 0x06: /* CTRL + F */ if (_el_move_cursor(VK_RIGHT, 0)) { _el_clean_exit(); return NULL; } break; /* backward-char */ case 0x02: /* CTRL + B */ if (_el_move_cursor(VK_LEFT, 0)) { _el_clean_exit(); return NULL; } break; /* previous-line */ case 0x10: /* CTRL + P */ if (_el_display_prev_hist()) { _el_clean_exit(); return NULL; } break; /* next-line */ case 0x0E: /* CTRL + N */ if (_el_display_next_hist()) { _el_clean_exit(); return NULL; } break; /* delete char */ case 0x04: /* CTRL + D */ if (rl_point != wcslen(_el_line_buffer)) { if (_el_delete_char(VK_DELETE, 1)) { _el_clean_exit(); return NULL; } _el_compl_index = 0; compl_pos = -1; } break; /* if it is a printable character, print it NOTE: I have later commented out the iswprint() check since for instance it prevents the euro sign from being printed */ default: /*if (iswprint(buf[0])) {*/ _el_compl_index = 0; compl_pos = -1; if (_el_insert_char(buf, 1)) { _el_clean_exit(); return NULL; } /*}*/ } } } /* if it was not a keyboard event, just remove it from buffer */ else if (!ReadConsoleInput(_el_h_in, &irBuffer, 1, &count)) { _el_clean_exit(); return NULL; } } else { /* wait for console input */ WaitForSingleObject(_el_h_in, INFINITE); } } printf("\n"); history_set_pos(history_length()); /* if CTRL+C has been pressed, return an empty string */ if (_el_line_buffer) { if (_el_ctrl_c_pressed) { n = (int)wcslen(_el_line_buffer) - rl_point; if (n) { _el_set_cursor(n); } _el_line_buffer[0] = _T('\0'); } _el_w2mb(_el_line_buffer, &rl_line_buffer); ret_string = _strdup(rl_line_buffer); } _el_clean_exit(); return ret_string; }
static void wpa_cli_interactive(void) { #define max_args 10 char cmdbuf[256], *cmd, *argv[max_args], *pos; int argc; #ifdef CONFIG_READLINE char *home, *hfile = NULL; #endif /* CONFIG_READLINE */ printf("\nInteractive mode\n\n"); #ifdef CONFIG_READLINE rl_attempted_completion_function = wpa_cli_completion; home = getenv("HOME"); if (home) { const char *fname = ".wpa_cli_history"; int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; hfile = os_malloc(hfile_len); if (hfile) { os_snprintf(hfile, hfile_len, "%s/%s", home, fname); hfile[hfile_len - 1] = '\0'; read_history(hfile); stifle_history(100); } } #endif /* CONFIG_READLINE */ do { wpa_cli_recv_pending(monitor_conn, 0, 0); #ifndef CONFIG_NATIVE_WINDOWS alarm(1); #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef CONFIG_READLINE cmd = readline("> "); if (cmd && *cmd) { HIST_ENTRY *h; while (next_history()) ; h = previous_history(); if (h == NULL || os_strcmp(cmd, h->line) != 0) add_history(cmd); next_history(); } #else /* CONFIG_READLINE */ printf("> "); cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); #endif /* CONFIG_READLINE */ #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ if (cmd == NULL) break; wpa_cli_recv_pending(monitor_conn, 0, 0); pos = cmd; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } argc = 0; pos = cmd; for (;;) { while (*pos == ' ') pos++; if (*pos == '\0') break; argv[argc] = pos; argc++; if (argc == max_args) break; if (*pos == '"') { char *pos2 = os_strrchr(pos, '"'); if (pos2) pos = pos2 + 1; } while (*pos != '\0' && *pos != ' ') pos++; if (*pos == ' ') *pos++ = '\0'; } if (argc) wpa_request(ctrl_conn, argc, argv); if (cmd != cmdbuf) os_free(cmd); } while (!wpa_cli_quit); #ifdef CONFIG_READLINE if (hfile) { /* Save command history, excluding lines that may contain * passwords. */ HIST_ENTRY *h; history_set_pos(0); h = next_history(); while (h) { char *p = h->line; while (*p == ' ' || *p == '\t') p++; if (os_strncasecmp(p, "pa", 2) == 0 || os_strncasecmp(p, "o", 1) == 0 || os_strncasecmp(p, "n", 1)) { h = remove_history(where_history()); if (h) { os_free(h->line); os_free(h->data); os_free(h); } h = current_history(); } else { h = next_history(); } } write_history(hfile); os_free(hfile); } #endif /* CONFIG_READLINE */ }
void history_adjust_pos(history *hist, int adjustment) { if(!hist) return; history_set_pos(hist, hist->_history_index + adjustment); }