16 #include <sys/socket.h> 18 #include <sys/epoll.h> 19 #include <sys/ioctl.h> 32 #include <arpa/telnet.h> 38 #define SOCKET_FILE "/run/vpp/cli.sock" 48 term = is_interactive ? getenv (
"TERM") :
"vppctl";
53 IAC, SB, TELOPT_TTYPE, 0, term, IAC, SE);
62 if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
70 ws.ws_col >> 8, ws.ws_col & 0xff,
71 ws.ws_row >> 8, ws.ws_row & 0xff, IAC, SE);
84 tcsetattr (STDIN_FILENO, TCSAFLUSH, &
orig_tio);
93 while (i <
vec_len (s->rx_buffer))
95 if (s->rx_buffer[i] == IAC)
97 if (s->rx_buffer[i + 1] == SB)
100 char opt = s->rx_buffer[i + 2];
102 while (s->rx_buffer[i] != IAC)
111 if (opt == TELOPT_TTYPE)
116 else if (is_interactive && opt == TELOPT_NAWS)
123 TELCMD (s->rx_buffer[i + 1]),
124 TELOPT (s->rx_buffer[i + 2]));
142 struct epoll_event event;
149 int is_interactive = 0;
160 if (argc > 1 && strncmp (argv[0],
"-s", 2) == 0)
170 cmd =
format (cmd,
"%s%c", (argv++)[0], argc ?
' ' : 0);
178 is_interactive = isatty (STDIN_FILENO) && cmd == 0;
185 if (sigaction (SIGWINCH, &sa, 0) < 0)
193 if (sigaction (SIGTERM, &sa, 0) < 0)
200 if (tcgetattr (STDIN_FILENO, &
orig_tio) < 0)
209 tio.c_lflag &= ~(ECHO | ICANON | IEXTEN);
213 if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &tio) < 0)
220 efd = epoll_create1 (0);
223 event.events = EPOLLIN | EPOLLPRI | EPOLLERR;
224 event.data.fd = STDIN_FILENO;
225 if (epoll_ctl (efd, EPOLL_CTL_ADD, STDIN_FILENO, &event) != 0)
236 event.events = EPOLLIN | EPOLLPRI | EPOLLERR;
237 event.data.fd = s->fd;
238 if (epoll_ctl (efd, EPOLL_CTL_ADD, s->fd, &event) != 0)
254 if ((n = epoll_wait (efd, &event, 1, -1)) < 0)
267 if (event.data.fd == STDIN_FILENO)
275 n = read (STDIN_FILENO, c,
sizeof (c));
288 else if (event.data.fd == s->fd)
302 u8 *p = str, *q = str;
307 while (q < (p + len) && *q)
310 n = write (STDOUT_FILENO, p, q - p);
317 while (q < (p + len) && !*q)
329 if (do_quit && do_quit < acked)
336 if (cmd && sent_ttype)
365 tcsetattr (STDIN_FILENO, TCSAFLUSH, &
orig_tio);
Optimized string handling code, including c11-compliant "safe C library" variants.
static void send_naws(clib_socket_t *s)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
clib_error_t * clib_socket_init(clib_socket_t *s)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static void signal_handler_term(int signum)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
int main(int argc, char *argv[])
static u8 * process_input(u8 *str, clib_socket_t *s, int is_interactive, int *sent_ttype)
#define clib_error_return(e, args...)
static clib_error_t * clib_socket_close(clib_socket_t *sock)
#define clib_error_return_unix(e, args...)
void * clib_mem_init(void *heap, uword size)
volatile int window_resized
#define vec_free(V)
Free vector's memory (no header).
#define clib_warning(format, args...)
static void send_ttype(clib_socket_t *s, int is_interactive)
#define CLIB_SOCKET_F_IS_CLIENT
#define clib_error_report(e)
struct _socket_t clib_socket_t
static clib_error_t * clib_socket_rx(clib_socket_t *s, int n_bytes)
static int clib_socket_rx_end_of_file(clib_socket_t *s)
static void * clib_socket_tx_add(clib_socket_t *s, int n_bytes)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define clib_unix_warning(format, args...)
static clib_error_t * clib_socket_tx(clib_socket_t *s)
static void signal_handler_winch(int signum)
void clib_socket_tx_add_formatted(clib_socket_t *s, char *fmt,...)