Пример #1
0
static void
handle_sigTSTP(int signo)
{
    sigset_t all_signals;
    int error, saved_errno = errno;

    DEBUG_RANDOM_SLEEP;
    sigfillset(&all_signals);

    DPRINTF2(DEBUG_SIGNALS, "got %s, sending it to pgid %d", signal_name(signo), command_pid);
    zero_select_timeout();
    /* Hand the SIGTSTP down to command and its process group */
    if (command_pid && (error = kill(-command_pid, SIGTSTP))) {
        myerror(FATAL|USE_ERRNO, "Failed to deliver SIGTSTP");
    }

    if (within_line_edit)
        save_rl_state();


    mysignal(SIGTSTP, SIG_DFL);   /* reset disposition to default (i.e. suspend) */
    sigprocmask(SIG_UNBLOCK, &all_signals, NULL); /* respond to sleep- and wake-up signals  */
    kill(getpid(), SIGTSTP); /* suspend */
    /* keyboard gathers dust, kingdoms crumble,.... */

    /* .... */

    /* Beautiful princess types "fg", (or her father tries to kill us...) and we wake up HERE: */
    sigprocmask(SIG_BLOCK, &all_signals, NULL);
    mysignal(SIGTSTP, &handle_sigTSTP);
    DPRINTF0(DEBUG_SIGNALS, "woken up");

    /* On most systems, command's process group will have been woken up by the handler of
       the signal that woke us up. This doesn't seem to happen for SIGCONT on QNX, so here goes: */

#ifdef __QNX__
    if (command_pid && (error = kill(-command_pid, SIGCONT))) {
        myerror(FATAL|USE_ERRNO, "Failed to deliver SIGCONT");
    }
#endif

    if (within_line_edit) {
        restore_rl_state();
    } else {
        set_echo(FALSE);
        cr();
        if (skip_rlwrap())
            return;
        move_cursor_to_start_of_prompt(ERASE);
        cook_prompt_if_necessary();
        my_putstr(saved_rl_state.cooked_prompt);
    }
    adapt_tty_winsize(STDIN_FILENO, master_pty_fd);       /* just in case */
    errno = saved_errno;
    sigprocmask(SIG_UNBLOCK, &all_signals, NULL);
}
Пример #2
0
static void
pass_on_signal(int signo)
{
    int ret, saved_errno = errno, pass_it_on = TRUE;
    DEBUG_RANDOM_SLEEP;
    zero_select_timeout();
#ifdef DEBUG
    log_named_signal(signo);
#endif

    if(pass_on_sigINT_as_sigTERM && signo == SIGINT)
        signo=SIGTERM;

    switch (signo) {
    case SIGWINCH: /* non-POSIX, but present on most systems */
        /* Make slave pty's winsize equal to that of STDIN. Pass the signal on *only if*
           winsize has changed. This is particularly important because we have the slave pty
           still open - when we pass on the signal the child will probably do a TIOCSWINSZ ioctl()
           on the slave pty  - causing us (the parent) to get a SIGWINCH again, thus getting stuck in a loop */
        pass_it_on = adapt_tty_winsize(STDIN_FILENO, master_pty_fd);
        break;
    case SIGTERM:
        sigterm_received = TRUE;
        break;
    default:
        break;
    }
    if (!command_pid)
        pass_it_on = FALSE;         /* no child (yet) to pass it on to */

    if (pass_it_on) {             /* we resend the signal to the process *group* of the child */
        ret = kill( -command_pid, signo);
        DPRINTF3(DEBUG_SIGNALS, "kill(%d,%s) = %d", -command_pid, signal_name(signo), ret);
        we_just_got_a_signal_or_EOF = TRUE; /* signal to main loop that next command output should leave the prompt alone */
    }
    errno = saved_errno;

}
Пример #3
0
static void
line_handler(char *line)
{
  char *rewritten_line, *filtered_line;
  
  if (line == NULL) {           /* EOF on input, forward it  */
    DPRINTF1(DEBUG_READLINE, "EOF detected, writing character %d", term_eof);
    /* colour_the_prompt = FALSE; don't mess with the cruft that may come out of dying command @@@ but command may not die!*/
    write_EOF_to_master_pty();
  } else {
    if (*line &&                 /* forget empty lines  */
        redisplay &&             /* forget passwords    */
        !forget_line &&          /* forget lines entered by CTRL-O */
        !match_regexp(line, forget_regexp, TRUE)) {     /* forget lines (case-inseitively) matching -g option regexp */ 
      my_add_history(line);
    }
    forget_line = FALSE; /* until CTRL-O is used again */

    /* Time for a design decision: when we send the accepted line to the client command, it will most probably be echoed
       back. We have two choices: we leave the entered line on screen and suppress just enough of the clients output (I
       believe this is what rlfe does), or we remove the entered input (but not the prompt!) and let it be replaced by
       the echo.

       This is what we do; as a bonus, if the program doesn't echo, e.g. at a password prompt, the **** which has been
       put there by our homegrown_redisplay function will be removed (@@@is this what we want?)

       I think this method is more natural for multi-line input as well, (we will actually see our multi-line input as
       multiple lines) but not everyone will agree with that.
          
       O.K, we know for sure that cursor is at start of line. When clients output arrives, it will be printed at
       just the right place - but first we 'll erase the user input (as it may be about to be changed by the filter) */
    
    rl_delete_text(0, rl_end);  /* clear line  (after prompt) */
    rl_point = 0;
    my_redisplay();             /* and redisplay (this time without user input, cf the comments for the line_handler() function below) */

    rewritten_line =
      (multiline_separator ? 
       search_and_replace(multiline_separator, "\n", line, 0, NULL,
                          NULL) : mysavestring(line));


    
      
    if (redisplay)
      filtered_line = pass_through_filter(TAG_INPUT, rewritten_line);
    else { /* password, none of filters business */
      pass_through_filter(TAG_INPUT, "***"); /* filter some input anyway, to keep filter in sync (result is discarded).  */
      filtered_line = mysavestring(rewritten_line);
    }   
    free(rewritten_line);
        
    
    /* do we have to adapt clients winzsize now? */
    if (deferred_adapt_commands_window_size) {
      adapt_tty_winsize(STDIN_FILENO, master_pty_fd);
      kill(-command_pid, SIGWINCH);
      deferred_adapt_commands_window_size = FALSE;
    }


    
    /*OK, now feed line to underlying command and wait for the echo to come back */
    put_in_output_queue(filtered_line);
    DPRINTF2(DEBUG_READLINE, "putting %d bytes %s in output queue", (int) strlen(rewritten_line),
             mangle_string_for_debug_log(rewritten_line, 40));
    write_EOL_to_master_pty(return_key ? &return_key : "\n");

    accepted_lines++;
    free_foreign(line);         /* free_foreign because line was malloc'ed by readline, not by rlwrap */
    free(filtered_line);        /* we're done with them  */
        
    return_key = 0;
    within_line_edit = FALSE;
    if(!RL_ISSTATE(RL_STATE_MACROINPUT)) /* when called during playback of a multi-line macro, line_handler() will be called more 
                                            than once whithout re-entering main_loop(). If we'd remove it here, the second call
                                            would crash  */ 
       rl_callback_handler_remove();
    set_echo(FALSE);
    free(saved_rl_state.input_buffer);
    free(saved_rl_state.raw_prompt);
    free(saved_rl_state.cooked_prompt); 
    
    saved_rl_state.input_buffer = mysavestring("");
    saved_rl_state.raw_prompt = mysavestring("");
    saved_rl_state.cooked_prompt = NULL;
    saved_rl_state.point = 0;
    saved_rl_state.already_saved = TRUE;
    redisplay  = TRUE;

    if (one_shot_rlwrap)
      write_EOF_to_master_pty();
  }
}