File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / client / birdc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:56 2019 UTC (5 years, 2 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

    1: /*
    2:  *	BIRD Client - Readline variant I/O
    3:  *
    4:  *	(c) 1999--2004 Martin Mares <mj@ucw.cz>
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  */
    8: 
    9: #include <stdio.h>
   10: #include <stdlib.h>
   11: #include <unistd.h>
   12: #include <termios.h>
   13: 
   14: #include <readline/readline.h>
   15: #include <readline/history.h>
   16: #include <curses.h>
   17: 
   18: #include "nest/bird.h"
   19: #include "lib/resource.h"
   20: #include "lib/string.h"
   21: #include "client/client.h"
   22: 
   23: static int input_hidden_end;
   24: static int prompt_active;
   25: 
   26: /*** Input ***/
   27: 
   28: /* HACK: libreadline internals we need to access */
   29: extern int _rl_vis_botlin;
   30: extern void _rl_move_vert(int);
   31: 
   32: #define HISTORY "/.birdc_history"
   33: static char *history_file;
   34: 
   35: static void
   36: add_history_dedup(char *cmd)
   37: {
   38:   /* Add history line if it differs from the last one */
   39:   HIST_ENTRY *he = history_get(history_length);
   40:   if (!he || strcmp(he->line, cmd))
   41:     add_history(cmd);
   42: }
   43: 
   44: static void
   45: input_got_line(char *cmd_buffer)
   46: {
   47:   if (!cmd_buffer)
   48:     {
   49:       cleanup();
   50:       exit(0);
   51:     }
   52: 
   53:   if (cmd_buffer[0])
   54:     {
   55:       add_history_dedup(cmd_buffer);
   56:       submit_command(cmd_buffer);
   57:     }
   58: 
   59:   free(cmd_buffer);
   60: }
   61: 
   62: void
   63: input_start_list(void)
   64: {
   65:   /* Leave the currently edited line and make space for listing */
   66:   _rl_move_vert(_rl_vis_botlin);
   67: #ifdef HAVE_RL_CRLF
   68:   rl_crlf();
   69: #endif
   70: }
   71: 
   72: void
   73: input_stop_list(void)
   74: {
   75:   /* Reprint the currently edited line after listing */
   76:   rl_on_new_line();
   77:   rl_redisplay();
   78: }
   79: 
   80: static int
   81: input_complete(int arg UNUSED, int key UNUSED)
   82: {
   83:   static int complete_flag;
   84:   char buf[256];
   85: 
   86:   if (rl_last_func != input_complete)
   87:     complete_flag = 0;
   88:   switch (cmd_complete(rl_line_buffer, rl_point, buf, complete_flag))
   89:     {
   90:     case 0:
   91:       complete_flag = 1;
   92:       break;
   93:     case 1:
   94:       rl_insert_text(buf);
   95:       break;
   96:     default:
   97:       complete_flag = 1;
   98: #ifdef HAVE_RL_DING
   99:       rl_ding();
  100: #endif
  101:     }
  102:   return 0;
  103: }
  104: 
  105: static int
  106: input_help(int arg, int key UNUSED)
  107: {
  108:   int i, in_string, in_bracket;
  109: 
  110:   if (arg != 1)
  111:     return rl_insert(arg, '?');
  112: 
  113:   in_string = in_bracket = 0;
  114:   for (i = 0; i < rl_point; i++)
  115:     {
  116:    
  117:       if (rl_line_buffer[i] == '"')
  118: 	in_string = ! in_string;
  119:       else if (! in_string)
  120:         {
  121: 	  if (rl_line_buffer[i] == '[')
  122: 	    in_bracket++;
  123: 	  else if (rl_line_buffer[i] == ']')
  124: 	    in_bracket--;
  125:         }
  126:     }
  127: 
  128:   /* `?' inside string or path -> insert */
  129:   if (in_string || in_bracket)
  130:     return rl_insert(1, '?');
  131: 
  132:   rl_begin_undo_group();		/* HACK: We want to display `?' at point position */
  133:   rl_insert_text("?");
  134:   rl_redisplay();
  135:   rl_end_undo_group();
  136:   input_start_list();
  137:   cmd_help(rl_line_buffer, rl_point);
  138:   rl_undo_command(1, 0);
  139:   input_stop_list();
  140:   return 0;
  141: }
  142: 
  143: void
  144: history_init(void)
  145: {
  146:   const char *homedir = getenv("HOME");
  147:   if (!homedir)
  148:     homedir = ".";
  149:   history_file = malloc(strlen(homedir) + sizeof(HISTORY));
  150:   if (!history_file)
  151:     die("couldn't alloc enough memory for history file name");
  152: 
  153:   sprintf(history_file, "%s%s", homedir, HISTORY);
  154:   read_history(history_file);
  155: }
  156: 
  157: void
  158: input_init(void)
  159: {
  160:   if (interactive)
  161:     history_init();
  162:   rl_readline_name = "birdc";
  163:   rl_add_defun("bird-complete", input_complete, '\t');
  164:   rl_add_defun("bird-help", input_help, '?');
  165:   rl_callback_handler_install("bird> ", input_got_line);
  166: 
  167:   // rl_get_screen_size();
  168:   term_lns = LINES;
  169:   term_cls = COLS;
  170: 
  171:   prompt_active = 1;
  172: 
  173:   // readline library does strange things when stdin is nonblocking.
  174:   // if (fcntl(0, F_SETFL, O_NONBLOCK) < 0)
  175:   //   DIE("fcntl");
  176: }
  177: 
  178: static void
  179: input_reveal(void)
  180: {
  181:   /* need this, otherwise some lib seems to eat pending output when
  182:      the prompt is displayed */
  183:   fflush(stdout);
  184:   tcdrain(STDOUT_FILENO);
  185: 
  186:   rl_end = input_hidden_end;
  187:   rl_expand_prompt("bird> ");
  188:   rl_forced_update_display();
  189: 
  190:   prompt_active = 1;
  191: }
  192: 
  193: static void
  194: input_hide(void)
  195: {
  196:   input_hidden_end = rl_end;
  197:   rl_end = 0;
  198:   rl_expand_prompt("");
  199:   rl_redisplay();
  200: 
  201:   prompt_active = 0;
  202: }
  203: 
  204: void
  205: input_notify(int prompt)
  206: {
  207:   if (prompt == prompt_active)
  208:     return;
  209: 
  210:   if (prompt)
  211:     input_reveal();
  212:   else
  213:     input_hide();
  214: }
  215: 
  216: void
  217: input_read(void)
  218: {
  219:   rl_callback_read_char();
  220: }
  221: 
  222: void
  223: more_begin(void)
  224: {
  225: }
  226: 
  227: void
  228: more_end(void)
  229: {
  230: }
  231: 
  232: void
  233: cleanup(void)
  234: {
  235:   if (init)
  236:     return;
  237: 
  238:   input_hide();
  239:   if (interactive)
  240:     write_history(history_file);
  241:   rl_callback_handler_remove();
  242: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>