Example #1
0
/*
 * Handle key to cut and discard line after cursor
 */
static void rl_key_cut (void)
{
#ifdef ANSI_TERM
    while (rl_delete ())
        ;
    rl_recheck (TRUE);
#else
    while (rl_delete ())
        rl_recheck;
#endif
    rl_tab_state = 0;
}
Example #2
0
/*
 * Handle delete key
 */
static void rl_key_delete (void)
{
    if (rl_tab_state > 0)
        rl_tab_cancel ();
    rl_delete ();
    rl_recheck (TRUE);
}
Example #3
0
int
rl_vi_overstrike (int count, int key)
{
  int i;

  if (_rl_vi_doing_insert == 0)
    {
      _rl_vi_doing_insert = 1;
      rl_begin_undo_group ();
    }

  for (i = 0; i < count; i++)
    {
      vi_replace_count++;
      rl_begin_undo_group ();

      if (rl_point < rl_end)
	{
	  rl_delete (1, key);
	  rl_insert (1, key);
	}
      else
	rl_insert (1, key);

      rl_end_undo_group ();
    }
  return (0);
}
Example #4
0
int
rl_vi_change_char (int count, int key)
{
  int c;

  if (vi_redoing)
    c = _rl_vi_last_replacement;
  else
    _rl_vi_last_replacement = c = rl_getc (rl_instream);

  if (c == '\033' || c == CTRL ('C'))
    return -1;

  while (count-- && rl_point < rl_end)
    {
      rl_begin_undo_group ();

      rl_delete (1, c);
      rl_insert (1, c);
      if (count == 0)
	rl_backward (1, c);

      rl_end_undo_group ();
    }
  return (0);
}
Example #5
0
static int
_rl_vi_change_mbchar_case(int count)
{
  wchar_t wc;
  char mb[MB_LEN_MAX + 1];
  int mb_len;
  mbstate_t ps;

  memset(&ps, 0, sizeof(mbstate_t));
  if (_rl_adjust_point(rl_line_buffer, rl_point, &ps) > 0)
    count--;
  while (count-- && (rl_point < rl_end))
    {
      mbrtowc(&wc, (rl_line_buffer + rl_point),
              (size_t)(rl_end - rl_point), &ps);
      if (iswupper(wc))
	wc = towlower(wc);
      else if (iswlower(wc))
	wc = towupper(wc);
      else
	{
	  /* Just skip over chars neither upper nor lower case */
	  rl_forward_char(1, 0);
	  continue;
	}

      /* Vi is kind of strange here. */
      if (wc)
	{
	  mb_len = wctomb(mb, wc);
	  if (mb_len >= 0)
	    mb[mb_len] = '\0';
	  rl_begin_undo_group();
	  rl_delete(1, 0);
	  rl_insert_text(mb);
	  rl_end_undo_group();
	  rl_vi_check();
	}
      else
        rl_forward_char(1, 0);
    }

  return 0;
}
Example #6
0
int
rl_vi_change_case(int count, int ignore)
{
  char c = 0;

  /* Do NOT try this on an empty line: */
  if (rl_point >= rl_end)
    return (0);

#if defined(HANDLE_MULTIBYTE)
  if ((MB_CUR_MAX > 1) && (rl_byte_oriented == 0))
    return (_rl_vi_change_mbchar_case(count));
#endif

  while (count-- && (rl_point < rl_end))
    {
      if (_rl_uppercase_p(rl_line_buffer[rl_point]))
	c = (char)_rl_to_lower(rl_line_buffer[rl_point]);
      else if (_rl_lowercase_p(rl_line_buffer[rl_point]))
	c = (char)_rl_to_upper(rl_line_buffer[rl_point]);
      else
	{
	  /* Just skip over characters neither upper nor lower case. */
	  rl_forward_char (1, c);
	  continue;
	}

      /* Vi is kind of strange here. */
      if (c)
	{
	  rl_begin_undo_group ();
	  rl_delete (1, c);
	  _rl_insert_char (1, c);
	  rl_end_undo_group ();
	  rl_vi_check ();
        }
      else
	rl_forward_char (1, c);
    }
  return (0);
}
Example #7
0
/*
 * Handle tab key - continue tabbing backwards
 */
static void rl_key_shifttab (void)
{
    str_s str = { NULL, 0, 0 };
    const char *display;
    int off;
    UWORD columns;

    if (rl_tab_state <= 0)
    {
        printf ("\a");
        return;
    }

    rl_linecompress (&rl_temp, rl_tab_pos, rl_ucspos);
    rl_tab_cont = rl_tab_getprev (&rl_temp);
    rl_left (rl_tab_common);

    for ( ; rl_tab_len; rl_tab_len--)
        rl_delete ();
    if (!rl_tab_cont)
    {
        printf ("\a");
        rl_tab_state = 0;
        rl_recheck (TRUE);
        return;
    }

    str.txt = rl_tab_alias ? rl_tab_alias->alias : rl_tab_cont->nick;
    str.len = strlen (str.txt);
    for (off = 0; off < str.len; )
    {
        wint_tt ucs = ConvGetUTF8 (&str, &off);
        rl_analyze_ucs (ucs, &display, &columns);
        rl_insert_basic (ucs, s_sprintf ("%s%s%s", rl_colon.txt, display, rl_coloff.txt),
                         strlen (display) + rl_colon.len + rl_coloff.len, columns & 0xff);
        rl_tab_len++;
    }
    rl_left (rl_tab_len - rl_tab_common);
    rl_recheck (TRUE);
}
Example #8
0
/*
 * Cancel the current tab contact
 */
static void rl_tab_cancel (void)
{
    str_s str = { NULL, 0, 0 };
    const char *display;
    int i, off;
    UWORD columns;
    
    if (rl_tab_state <= 0)
       return;
    rl_left (rl_tab_common);
    for ( ; rl_tab_len; rl_tab_len--)
        rl_delete ();
    str.txt = rl_tab_alias ? rl_tab_alias->alias : rl_tab_cont->nick;
    str.len = strlen (str.txt);
    for (off = i = 0; off < str.len && i < rl_tab_common; i++)
    {
        wint_tt ucs = ConvGetUTF8 (&str, &off);
        rl_analyze_ucs (ucs, &display, &columns);
        rl_insert_basic (ucs, display, strlen (display), columns & 0xff);
    }
    rl_tab_state = 0;
    rl_recheck (TRUE);
}
Example #9
0
int
rl_vi_change_case (int count, int ignore)
{
  char c = 0;

  /* Don't try this on an empty line. */
  if (rl_point >= rl_end)
    return (0);

  while (count-- && rl_point < rl_end)
    {
      if (uppercase_p (rl_line_buffer[rl_point]))
	c = to_lower (rl_line_buffer[rl_point]);
      else if (lowercase_p (rl_line_buffer[rl_point]))
	c = to_upper (rl_line_buffer[rl_point]);
      else
	{
	  /* Just skip over characters neither upper nor lower case. */
	  rl_forward (1, c);
	  continue;
	}

      /* Vi is kind of strange here. */
      if (c)
	{
	  rl_begin_undo_group ();
	  rl_delete (1, c);
	  rl_insert (1, c);
	  rl_end_undo_group ();
	  rl_vi_check ();
        }
      else
	rl_forward (1, c);
    }
  return (0);
}
Example #10
0
/*
 * Handle tab key - start or continue tabbing
 */
static void rl_key_tab (void)
{
    str_s str = { NULL, 0, 0 };
    strc_t ins;
    const char *display;
    int i, off;
    UWORD columns;

    if (rl_tab_state == -1)
    {
        rl_insert (9);
        return;
    }

    if (!rl_tab_state)
    {
        if (!rl_ucs.len)
        {
            rl_insert ('m');
            rl_insert ('s');
            rl_insert ('g');
            rl_insert (' ');
        }
        for (i = 0; i < rl_ucspos; i++)
        {
            if (rl_ucs_at (&rl_ucs, i) == ' ')
            {
                rl_tab_index = 0;
                rl_tab_state = 1;
                rl_tab_pos = i + 1;
                rl_linecompress (&rl_temp, rl_tab_pos, rl_ucspos);
                if ((rl_tab_cont = rl_tab_getnext (&rl_temp)))
                {
                    ins = ConvTo (COLQUOTE, ENC(enc_loc));
                    s_init (&rl_colon, "", 0);
                    s_catn (&rl_colon, ins->txt, ins->len);
                    ins = ConvTo (COLNONE, ENC(enc_loc));
                    s_init (&rl_coloff, "", 0);
                    s_catn (&rl_coloff, ins->txt, ins->len);

                    while (rl_ucspos > rl_tab_pos)
                        rl_left (1), rl_tab_len++;
                    rl_tab_common = rl_tab_len;
                    break;
                }
            }
        }
        if (!rl_tab_state)
        {
            printf ("\a");
            return;
        }
    }
    else
    {
        rl_linecompress (&rl_temp, rl_tab_pos, rl_ucspos);
        rl_tab_cont = rl_tab_getnext (&rl_temp);
        rl_left (rl_tab_common);
    }
    for ( ; rl_tab_len; rl_tab_len--)
        rl_delete ();
    if (!rl_tab_cont)
    {
        printf ("\a");
        rl_tab_state = 0;
        rl_recheck (TRUE);
        return;
    }

    str.txt = rl_tab_alias ? rl_tab_alias->alias : rl_tab_cont->nick;
    str.len = strlen (str.txt);
    for (off = 0; off < str.len; )
    {
        wint_tt ucs = ConvGetUTF8 (&str, &off);
        rl_analyze_ucs (ucs, &display, &columns);
        rl_insert_basic (ucs, s_sprintf ("%s%s%s", rl_colon.txt, display, rl_coloff.txt),
                         strlen (display) + rl_colon.len + rl_coloff.len, columns & 0xff);
        rl_tab_len++;
    }
    rl_left (rl_tab_len - rl_tab_common);
    rl_recheck (TRUE);
}
Example #11
0
/*
 *  Refresh a request, by using proxy_retry_delay, cleanup_delay,
 *  max_request_time, etc.
 *
 *  When walking over the request list, all of the per-request
 *  magic is done here.
 */
static int refresh_request(REQUEST *request, void *data)
{
	rl_walk_t *info = (rl_walk_t *) data;
	time_t difference;
	child_pid_t child_pid;

	rad_assert(request->magic == REQUEST_MAGIC);

	/*
	 *  If the request is marked as a delayed reject, AND it's
	 *  time to send the reject, then do so now.
	 */
	if (request->finished &&
	    ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0)) {
		rad_assert(request->child_pid == NO_SUCH_CHILD_PID);

		difference = info->now - request->timestamp;
		if (difference >= (time_t) mainconfig.reject_delay) {

			/*
			 *  Clear the 'delayed reject' bit, so that we
			 *  don't do this again.
			 */
			request->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
			rad_send(request->reply, request->packet,
				 request->secret);
		}
	}

	/*
	 *  If the request has finished processing, AND it's child has
	 *  been cleaned up, AND it's time to clean up the request,
	 *  OR, it's an accounting request.  THEN, go delete it.
	 *
	 *  If this is a request which had the "don't cache" option
	 *  set, then delete it immediately, as it CANNOT have a
	 *  duplicate.
	 */
	if (request->finished &&
	    ((request->timestamp + mainconfig.cleanup_delay <= info->now) ||
	     ((request->options & RAD_REQUEST_OPTION_DONT_CACHE) != 0))) {
		rad_assert(request->child_pid == NO_SUCH_CHILD_PID);

		/*
		 *  Request completed, delete it, and unlink it
		 *  from the currently 'alive' list of requests.
		 */
		DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
				request->number, request->packet->id,
				(unsigned long) request->timestamp);

		/*
		 *  Delete the request.
		 */
		rl_delete(request);
		return RL_WALK_CONTINUE;
	}

	/*
	 *  Maybe the child process handling the request has hung:
	 *  kill it, and continue.
	 */
	if ((request->timestamp + mainconfig.max_request_time) <= info->now) {
		int number;

		child_pid = request->child_pid;
		number = request->number;

		/*
		 *	There MUST be a RAD_PACKET reply.
		 */
		rad_assert(request->reply != NULL);

		/*
		 *	If we've tried to proxy the request, and
		 *	the proxy server hasn't responded, then
		 *	we send a REJECT back to the caller.
		 *
		 *	For safety, we assert that there is no child
		 *	handling the request.  If the assertion fails,
		 *	it means that we've sent a proxied request to
		 *	the home server, and the child thread is still
		 *	sitting on the request!
		 */
		if (request->proxy && !request->proxy_reply) {
			rad_assert(request->child_pid == NO_SUCH_CHILD_PID);

			radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s:%d",
			       request->number,
			       client_name(request->packet->src_ipaddr),
			       request->packet->src_port);
			request_reject(request);
			request->finished = TRUE;
			return RL_WALK_CONTINUE;
		}

		if (mainconfig.kill_unresponsive_children) {
			if (child_pid != NO_SUCH_CHILD_PID) {
				/*
				 *  This request seems to have hung
				 *   - kill it
				 */
#ifdef HAVE_PTHREAD_H
				radlog(L_ERR, "Killing unresponsive thread for request %d",
				       request->number);
				pthread_cancel(child_pid);
#endif
			} /* else no proxy reply, quietly fail */

			/*
			 *	Maybe we haven't killed it.  In that
			 *	case, print a warning.
			 */
		} else if ((child_pid != NO_SUCH_CHILD_PID) &&
			   ((request->options & RAD_REQUEST_OPTION_LOGGED_CHILD) == 0)) {
			radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d",
			       (unsigned long)child_pid, number);

			/*
			 *  Set the option that we've sent a log message,
			 *  so that we don't send more than one message
			 *  per request.
			 */
			request->options |= RAD_REQUEST_OPTION_LOGGED_CHILD;
		}

		/*
		 *  Send a reject message for the request, mark it
		 *  finished, and forget about the child.
		 */
		request_reject(request);
		request->child_pid = NO_SUCH_CHILD_PID;
		if (mainconfig.kill_unresponsive_children)
			request->finished = TRUE;
		return RL_WALK_CONTINUE;
	} /* the request has been in the queue for too long */

	/*
	 *  If the request is still being processed, then due to the
	 *  above check, it's still within it's time limit.  In that
	 *  case, don't do anything.
	 */
	if (request->child_pid != NO_SUCH_CHILD_PID) {
		return RL_WALK_CONTINUE;
	}

	/*
	 *  The request is finished.
	 */
	if (request->finished) goto setup_timeout;

	/*
	 *  We're not proxying requests at all.
	 */
	if (!mainconfig.proxy_requests) goto setup_timeout;

	/*
	 *  We're proxying synchronously, so we don't retry it here.
	 *  Some other code takes care of retrying the proxy requests.
	 */
	if (mainconfig.proxy_synchronous) goto setup_timeout;

	/*
	 *  The proxy retry delay is zero, meaning don't retry.
	 */
	if (mainconfig.proxy_retry_delay == 0) goto setup_timeout;

	/*
	 *  There is no proxied request for this packet, so there's
	 *  no proxy retries.
	 */
	if (!request->proxy) goto setup_timeout;

	/*
	 *  We've already seen the proxy reply, so we don't need
	 *  to send another proxy request.
	 */
	if (request->proxy_reply) goto setup_timeout;

	/*
	 *  It's not yet time to re-send this proxied request.
	 */
	if (request->proxy_next_try > info->now) goto setup_timeout;

	/*
	 *  If the proxy retry count is zero, then
	 *  we've sent the last try, and have NOT received
	 *  a reply from the end server.  In that case,
	 *  we don't bother trying again, but just mark
	 *  the request as finished, and go to the next one.
	 */
	if (request->proxy_try_count == 0) {
		rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
		request_reject(request);
		realm_disable(request->proxy->dst_ipaddr,request->proxy->dst_port);
		request->finished = TRUE;
		goto setup_timeout;
	}

	/*
	 *  We're trying one more time, so count down
	 *  the tries, and set the next try time.
	 */
	request->proxy_try_count--;
	request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;

	/* Fix up Acct-Delay-Time */
	if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
		VALUE_PAIR *delaypair;
		delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);

		if (!delaypair) {
			delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
			if (!delaypair) {
				radlog(L_ERR|L_CONS, "no memory");
				exit(1);
			}
			pairadd(&request->proxy->vps, delaypair);
		}
		delaypair->lvalue = info->now - request->proxy->timestamp;

		/* Must recompile the valuepairs to wire format */
		free(request->proxy->data);
		request->proxy->data = NULL;
	} /* proxy accounting request */

	/*
	 *  Assert that we have NOT seen the proxy reply yet.
	 *
	 *  If we HAVE seen it, then we SHOULD NOT be bugging the
	 *  home server!
	 */
	rad_assert(request->proxy_reply == NULL);

	/*
	 *  Send the proxy packet.
	 */
	request->proxy_outstanding++;
	rad_send(request->proxy, NULL, request->proxysecret);

setup_timeout:
	/*
	 *  Don't do more long-term checks, if we've got to wake
	 *  up now.
	 */
	if (info->smallest == 0) {
		return RL_WALK_CONTINUE;
	}

	/*
	 *  The request is finished.  Wake up when it's time to
	 *  clean it up.
	 */
	if (request->finished) {
		difference = (request->timestamp + mainconfig.cleanup_delay) - info->now;

		/*
		 *  If the request is marked up to be rejected later,
		 *  then wake up later.
		 */
		if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0) {
			if (difference >= (time_t) mainconfig.reject_delay) {
				difference = (time_t) mainconfig.reject_delay;
			}
		}

	} else if (request->proxy && !request->proxy_reply) {
		/*
		 *  The request is NOT finished, but there is an
		 *  outstanding proxy request, with no matching
		 *  proxy reply.
		 *
		 *  Wake up when it's time to re-send
		 *  the proxy request.
		 *
		 *  But in synchronous proxy, we don't retry but we update
		 *  the next retry time as NAS has not resent the request
		 *  in the given retry window.
		 */
		if (mainconfig.proxy_synchronous) {
			/*
			 *	If the retry_delay * count has passed,
			 *	then mark the realm dead.
			 */
			if (info->now > (request->timestamp + (mainconfig.proxy_retry_delay * mainconfig.proxy_retry_count))) {
				rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
				request_reject(request);
				
				realm_disable(request->proxy->dst_ipaddr,
					      request->proxy->dst_port);
				request->finished = TRUE;
				goto setup_timeout;
			}
			request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
		}
		difference = request->proxy_next_try - info->now;
	} else {
		/*
		 *  The request is NOT finished.
		 *
		 *  Wake up when it's time to kill the errant
		 *  thread/process.
		 */
		difference = (request->timestamp + mainconfig.max_request_time) - info->now;
	}

	/*
	 *  If the server is CPU starved, then we CAN miss a time
	 *  for servicing requests.  In which case the 'difference'
	 *  value will be negative.  select() doesn't like that,
	 *  so we fix it.
	 */
	if (difference < 0) {
		difference = 0;
	}

	/*
	 *  Update the 'smallest' time.
	 */
	if ((info->smallest < 0) ||
		(difference < info->smallest)) {
		info->smallest = difference;
	}

	return RL_WALK_CONTINUE;
}