char *process_new_output(const char* buffer, struct rl_state* UNUSED(state)) { char*last_nl, *old_prompt_plus_new_output, *new_prompt, *result; old_prompt_plus_new_output = append_and_free_old(saved_rl_state.raw_prompt, buffer); last_nl = strrchr(old_prompt_plus_new_output, '\n'); if (last_nl != NULL) { /* newline seen, will get new prompt: */ new_prompt = mysavestring(last_nl +1); /* chop off the part after the last newline - this will be the new prompt */ *last_nl = '\0'; old_prompt_plus_new_output = append_and_free_old (old_prompt_plus_new_output, "\n"); result = (impatient_prompt ? mysavestring (old_prompt_plus_new_output): pass_through_filter(TAG_OUTPUT, old_prompt_plus_new_output)); if (remember_for_completion) { feed_line_into_completion_list(result); /* feed output into completion list *after* filtering */ } } else { new_prompt = mysavestring(old_prompt_plus_new_output); result = mysavestring(""); } free(old_prompt_plus_new_output); saved_rl_state.raw_prompt = new_prompt; if (saved_rl_state.cooked_prompt) { free (saved_rl_state.cooked_prompt); saved_rl_state.cooked_prompt = NULL; } return result; }
/* * create pty pair and fork using my_pty_fork; parent returns immediately; child * executes the part of rlwrap's command line that remains after * read_options_and_command_name() has harvested rlwrap's own options */ static void fork_child(char *command_name, char **argv) { char *arg = argv[optind], *p, **argp; int pid; command_line = mysavestring(arg); for (argp = argv + optind + 1; *argp; argp++) { command_line = append_and_free_old (command_line, " "); command_line = append_and_free_old (command_line, *argp); } pid = my_pty_fork(&master_pty_fd, &saved_terminal_settings, &winsize); if (pid > 0) /* parent: */ return; else { /* child: */ DPRINTF1(DEBUG_TERMIO, "preparing to execute %s", arg); close_open_files_without_writing_buffers(); if (client_term_name) mysetenv("TERM", client_term_name); if (execvp(argv[optind], &argv[optind]) < 0) { if (last_opt > 0 && last_option_didnt_have_optional_argument) { /* e.g. 'rlwrap -a Password: sqlpus' will try to exec 'Password:'******'; !(){}"; *p; p++) /* does arg need shell quoting? */ if (strchr(arg,*p)) { arg = add3strings("'", arg,"'"); /* quote it */ break; } fprintf(stderr, "Did you mean '%s' to be an option argument?\nThen you should write -%c%s, without the space(s)\n", argv[optind], last_opt, arg); } myerror("Cannot execute %s", argv[optind]); /* stillborn child, parent will live on and display child's last gasps */ } } }
void put_in_output_queue(char *stuff) { output_queue = append_and_free_old(output_queue, stuff); DPRINTF3(DEBUG_TERMIO,"put %d bytes in output queue (which now has %d bytes): %s", (int) strlen(stuff), (int) strlen(output_queue), mangle_string_for_debug_log(stuff, 20)); }
char * mangle_string_for_debug_log(const char *string, int maxlen) { int total_length; char *mangled_char, *result; const char *p; /* good old K&R-style *p. I have become a fossil... */ if (!string) return mysavestring("(null)"); result = mysavestring(""); for(p = string, total_length = 0; *p; p++) { mangled_char = mangle_char_for_debug_log(*p, FALSE); total_length += strlen(mangled_char); if (maxlen && (total_length > maxlen)) { result = append_and_free_old(result, "..."); break; /* break *before* we reach maxlen */ } result = append_and_free_old(result, mangled_char); free(mangled_char); } return result; }
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; }