CLI : monitor command

This commit is contained in:
Adrien Bourmault 2021-07-15 23:05:55 +02:00
parent dee272db72
commit a95279b7ef
No known key found for this signature in database
GPG Key ID: 6EB408FE0ACEC664
1 changed files with 149 additions and 14 deletions

163
src/cli.c
View File

@ -1,5 +1,5 @@
//=-------------------------------------------------------------------------=// //=-------------------------------------------------------------------------=//
// Command line interface management module // // Command line interface main file //
// // // //
// Copyright © 2021 The Gem-graph Project // // Copyright © 2021 The Gem-graph Project //
// // // //
@ -22,11 +22,13 @@
#include "../include/base.h" #include "../include/base.h"
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include <termios.h> #include <termios.h>
#include <fcntl.h>
#define SEND_BUFFER_SIZE 80 #define SEND_BUFFER_SIZE 80
#define RECEIVE_BUFFER_SIZE 80 * 24 #define RECEIVE_BUFFER_SIZE 80 * 24
@ -43,6 +45,7 @@
#define KEY_ARROW_LEFT 68 #define KEY_ARROW_LEFT 68
#define KEY_DELETE 127 #define KEY_DELETE 127
#define C_CLEARSCREEN "\e[2J"
#define C_CLEARLINE "\e[2K" #define C_CLEARLINE "\e[2K"
#define C_CURSORLEFT "\e[1D" #define C_CURSORLEFT "\e[1D"
#define C_CURSORRIGHT "\e[1C" #define C_CURSORRIGHT "\e[1C"
@ -54,15 +57,25 @@
#define C_COLOR_BLUE "\e[01;34m" #define C_COLOR_BLUE "\e[01;34m"
#define C_COLOR_NORMAL "\e[0m" #define C_COLOR_NORMAL "\e[0m"
static char getch(void) #define NON_BLOCKING 1
//
// Get a character code from the keyboard
//
static inline int getch(bool nonBlocking)
{ {
char buf = 0; int buf = 0;
// old terminal // old terminal
struct termios old = {0}; struct termios old = {0};
// force flush stdout // force flush stdout
fflush(stdout); fflush(stdout);
// Set non-blocking mode if asked
if(nonBlocking)
fcntl(0, F_SETFL, O_NONBLOCK);
if(tcgetattr(0, &old) < 0) { if(tcgetattr(0, &old) < 0) {
printLog("%sError getting terminal settings! (%s)\n", printLog("%sError getting terminal settings! (%s)\n",
C_COLOR_RED, C_COLOR_RED,
@ -72,8 +85,6 @@ static char getch(void)
old.c_lflag &= ~ICANON; // disable buffered I/O old.c_lflag &= ~ICANON; // disable buffered I/O
old.c_lflag &= ~ECHO; // set no echo mode old.c_lflag &= ~ECHO; // set no echo mode
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if(tcsetattr(0, TCSANOW, &old) < 0) { if(tcsetattr(0, TCSANOW, &old) < 0) {
printLog("%sError setting terminal settings! (%s)\n", printLog("%sError setting terminal settings! (%s)\n",
@ -82,7 +93,12 @@ static char getch(void)
return -1; return -1;
} }
if(read(0, &buf, 1) < 0) { buf = getchar();
if(buf < 0) {
// Check target busy (try again)
if(errno == EAGAIN)
return 0;
printLog("%sError reading character! (%s)\n", printLog("%sError reading character! (%s)\n",
C_COLOR_RED, C_COLOR_RED,
strerror(errno)); strerror(errno));
@ -98,11 +114,120 @@ static char getch(void)
strerror(errno)); strerror(errno));
return -1; return -1;
} }
// Reset blocking mode
if(nonBlocking)
fcntl(0, F_SETFL, 0);
return buf; return buf;
} }
//
// Decorations
//
void decorateMonitor(struct winsize *terminalSize)
{
printf(C_CLEARSCREEN "\n");
void connectedCommunication(int sockfd) // print decorations
for (int i = 0; i < terminalSize->ws_col; i++) {
printf("*");
}
for (int i = 0;
i < (terminalSize->ws_row-2) * terminalSize->ws_col;
i++) {
if ((i % terminalSize->ws_col == 0) ||
(i % terminalSize->ws_col == terminalSize->ws_col - 1))
printf("|");
else
printf(" ");
}
for (int i = 0; i < terminalSize->ws_col; i++) {
printf("*");
}
fflush(stdout);
}
//
// Monitor mode main loop
//
int connectedMonitor(int sockfd)
{
char sendBuff[SEND_BUFFER_SIZE] = {0};
char receiveBuff[RECEIVE_BUFFER_SIZE] = {0};
int pleaseStop = 0;
char curChar;
int answerLength;
struct winsize terminalSize, oldTerminalSize;
// Get current terminal size
ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminalSize);
memcpy(&oldTerminalSize, &terminalSize, sizeof(struct winsize));
decorateMonitor(&terminalSize);
while (!pleaseStop) {
// Zeroing buffer
bzero(sendBuff, sizeof(sendBuff));
// Get current terminal size and redecorate if it has changed
ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminalSize);
if (terminalSize.ws_row != oldTerminalSize.ws_row ||
terminalSize.ws_col != oldTerminalSize.ws_col
) {
memcpy(&oldTerminalSize, &terminalSize, sizeof(struct winsize));
decorateMonitor(&terminalSize);
}
// Read command from terminal
curChar = getch(NON_BLOCKING);
if (curChar > 0) {
printLog("Char detected : %d\n", curChar);
}
switch (curChar) {
case 'q':
pleaseStop = true;
break;
}
/* // Otherwise send command to server */
/* send(sockfd, sendBuff, sizeof(sendBuff), 0); */
/* // Zeroing buffer */
/* bzero(receiveBuff, sizeof(receiveBuff)); */
/* // Reading server answer */
/* answerLength = recv(sockfd, receiveBuff, sizeof(receiveBuff), 0); */
/* // Detect disconnection */
/* if (answerLength == 0) { */
/* break; */
/* } */
/* // Detect null-string returned */
/* if (receiveBuff[0] == '\0') { */
/* // Invalid command */
/* } */
}
printf("%sEnd of monitoring session\n\e[0m", C_COLOR_YELLOW);
}
//
// Main CLI loop
//
void connectedCommandLine(int sockfd)
{ {
char sendBuff[SEND_BUFFER_SIZE] = {0}; char sendBuff[SEND_BUFFER_SIZE] = {0};
char receiveBuff[RECEIVE_BUFFER_SIZE] = {0}; char receiveBuff[RECEIVE_BUFFER_SIZE] = {0};
@ -113,8 +238,9 @@ void connectedCommunication(int sockfd)
char curChar; char curChar;
int curLineLength, curPosition, continueReadLine, answerLength; int curLineLength, curPosition, continueReadLine, answerLength;
char *exitCommand = "exit"; const char *exitCommand = "exit";
char *promptString = C_COLOR_BLUE "gem-graph console" C_COLOR_NORMAL "> "; const char *monitorCommand = "monitor";
const char *promptString = C_COLOR_BLUE "gem-graph console" C_COLOR_NORMAL "> ";
for (;;) { for (;;) {
// Zeroing buffer // Zeroing buffer
@ -126,7 +252,7 @@ void connectedCommunication(int sockfd)
curPosition = 0; curPosition = 0;
continueReadLine = 1; continueReadLine = 1;
historyModifier = -1; historyModifier = -1;
while (continueReadLine && (curChar = getch())) { while (continueReadLine && (curChar = getch(0))) {
switch (curChar) { switch (curChar) {
@ -164,9 +290,9 @@ void connectedCommunication(int sockfd)
break; break;
case KEY_ESCAPE: case KEY_ESCAPE:
if (getch() == KEY_DIRECTIONS) { if (getch(0) == KEY_DIRECTIONS) {
switch(getch()) { switch(getch(0)) {
case KEY_ARROW_UP: case KEY_ARROW_UP:
if (historyIndex <= 0) if (historyIndex <= 0)
@ -228,7 +354,7 @@ void connectedCommunication(int sockfd)
break; break;
default: default:
if (curLineLength < SEND_BUFFER_SIZE) { if (curLineLength < SEND_BUFFER_SIZE && curChar > 0) {
printf("%s", C_SAVE_CURSORPOS); printf("%s", C_SAVE_CURSORPOS);
memmove(sendBuff + curPosition + 1, sendBuff + curPosition, memmove(sendBuff + curPosition + 1, sendBuff + curPosition,
@ -266,6 +392,12 @@ void connectedCommunication(int sockfd)
break; break;
} }
// Launch monitor mode if asked
if (strcmp(monitorCommand, sendBuff) == 0) {
connectedMonitor(sockfd);
continue;
}
// Otherwise send command to server // Otherwise send command to server
send(sockfd, sendBuff, sizeof(sendBuff), 0); send(sockfd, sendBuff, sizeof(sendBuff), 0);
@ -290,6 +422,9 @@ void connectedCommunication(int sockfd)
printf("%sDisconnected\n\e[0m", C_COLOR_YELLOW); printf("%sDisconnected\n\e[0m", C_COLOR_YELLOW);
} }
//
// main
//
int main(void) int main(void)
{ {
int sockfd; int sockfd;
@ -321,7 +456,7 @@ int main(void)
printLog("%sConnected to server!\n\n", C_COLOR_GREEN); printLog("%sConnected to server!\n\n", C_COLOR_GREEN);
connectedCommunication(sockfd); connectedCommandLine(sockfd);
// close the socket // close the socket
close(sockfd); close(sockfd);