/* * 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; }
/* * Handle delete key */ static void rl_key_delete (void) { if (rl_tab_state > 0) rl_tab_cancel (); rl_delete (); rl_recheck (TRUE); }
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); }
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); }
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; }
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); }
/* * 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); }
/* * 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); }
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); }
/* * 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); }
/* * 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; }