mirror of
https://github.com/CPunch/Laika.git
synced 2026-02-01 06:10:03 +00:00
Added .clang-format, formatted codebase
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "lpeer.h"
|
||||
#include "ltask.h"
|
||||
#include "lsodium.h"
|
||||
|
||||
#include "ltask.h"
|
||||
#include "speer.h"
|
||||
|
||||
typedef struct sShell_client {
|
||||
typedef struct sShell_client
|
||||
{
|
||||
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
||||
struct sLaika_pollList pList;
|
||||
struct sLaika_taskService tService;
|
||||
@@ -31,7 +31,8 @@ bool shellC_poll(tShell_client *client, int timeout);
|
||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv);
|
||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id);
|
||||
|
||||
int shellC_addPeer(tShell_client *client, tShell_peer *peer); /* returns new peer id */
|
||||
/* returns new peer id */
|
||||
int shellC_addPeer(tShell_client *client, tShell_peer *peer);
|
||||
void shellC_rmvPeer(tShell_client *client, tShell_peer *peer, int id);
|
||||
|
||||
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row);
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#ifndef SHELLCMD_H
|
||||
#define SHELLCMD_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sclient.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef void (*shellCmdCallback)(tShell_client *client, int args, char *argc[]);
|
||||
|
||||
typedef struct sShell_cmdDef {
|
||||
typedef struct sShell_cmdDef
|
||||
{
|
||||
const char *cmd;
|
||||
const char *help;
|
||||
const char *syntax;
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
#ifndef SHELLPEER_H
|
||||
#define SHELLPEER_H
|
||||
|
||||
#include "lsodium.h"
|
||||
#include "lpeer.h"
|
||||
#include "lsodium.h"
|
||||
|
||||
typedef struct sShell_peer {
|
||||
typedef struct sShell_peer
|
||||
{
|
||||
uint8_t pub[crypto_kx_PUBLICKEYBYTES];
|
||||
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
||||
PEERTYPE type;
|
||||
OSTYPE osType;
|
||||
} tShell_peer;
|
||||
|
||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pub, char *hostname, char *inet, char *ipStr);
|
||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pub, char *hostname, char *inet,
|
||||
char *ipStr);
|
||||
void shellP_freePeer(tShell_peer *peer);
|
||||
|
||||
void shellP_printInfo(tShell_peer *peer);
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#ifndef SHELLTERM_H
|
||||
#define SHELLTERM_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "sclient.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <termios.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sclient.h"
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
TERM_BLACK,
|
||||
TERM_RED,
|
||||
TERM_GREEN,
|
||||
@@ -31,29 +32,34 @@ typedef enum {
|
||||
TERM_BRIGHT_WHITE
|
||||
} TERM_COLOR;
|
||||
|
||||
#define PRINTTAG(color) shellT_printf("\r%s[~]%s ", shellT_getForeColor(color), shellT_getForeColor(TERM_BRIGHT_WHITE))
|
||||
#define PRINTTAG(color) \
|
||||
shellT_printf("\r%s[~]%s ", shellT_getForeColor(color), shellT_getForeColor(TERM_BRIGHT_WHITE))
|
||||
|
||||
#define PRINTINFO(...) do { \
|
||||
PRINTTAG(TERM_BRIGHT_YELLOW); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while(0);
|
||||
#define PRINTINFO(...) \
|
||||
do { \
|
||||
PRINTTAG(TERM_BRIGHT_YELLOW); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while (0);
|
||||
|
||||
#define PRINTSUCC(...) do { \
|
||||
PRINTTAG(TERM_BRIGHT_GREEN); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while(0);
|
||||
#define PRINTSUCC(...) \
|
||||
do { \
|
||||
PRINTTAG(TERM_BRIGHT_GREEN); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while (0);
|
||||
|
||||
#define PRINTERROR(...) do { \
|
||||
PRINTTAG(TERM_BRIGHT_RED); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while(0);
|
||||
#define PRINTERROR(...) \
|
||||
do { \
|
||||
PRINTTAG(TERM_BRIGHT_RED); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
} while (0);
|
||||
|
||||
void shellT_conioTerm(void);
|
||||
void shellT_resetTerm(void);
|
||||
const char *shellT_getForeColor(TERM_COLOR);
|
||||
void shellT_printf(const char *format, ...);
|
||||
|
||||
/* waits for input for timeout (in ms). returns true if input is ready to be read, false if no events */
|
||||
/* waits for input for timeout (in ms). returns true if input is ready to be read, false if no
|
||||
* events */
|
||||
bool shellT_waitForInput(int timeout);
|
||||
int shellT_readRawInput(uint8_t *buf, size_t max);
|
||||
void shellT_writeRawOutput(uint8_t *buf, size_t sz);
|
||||
@@ -62,6 +68,7 @@ char shellT_getch(void);
|
||||
int shellT_kbget(void);
|
||||
void shellT_printPrompt(void);
|
||||
void shellT_setPrompt(char *prompt);
|
||||
void shellT_addChar(tShell_client *client, int c); /* processes input, moving cursor, adding char to cmd, etc. */
|
||||
/* processes input, moving cursor, adding char to cmd, etc. */
|
||||
void shellT_addChar(tShell_client *client, int c);
|
||||
|
||||
#endif
|
||||
@@ -1,39 +1,52 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ini.h"
|
||||
#include "sclient.h"
|
||||
#include "sterm.h"
|
||||
#include "ini.h"
|
||||
|
||||
#define STRING(x) #x
|
||||
#include <stdio.h>
|
||||
|
||||
#define STRING(x) #x
|
||||
#define MACROLITSTR(x) STRING(x)
|
||||
|
||||
const char *LOGO = "\n ██╗ █████╗ ██╗██╗ ██╗ █████╗\n ██║ ██╔══██╗██║██║ ██╔╝██╔══██╗\n ██║ ███████║██║█████╔╝ ███████║\n ██║ ██╔══██║██║██╔═██╗ ██╔══██║\n ███████╗██║ ██║██║██║ ██╗██║ ██║\n ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝";
|
||||
const char *LOGO =
|
||||
"\n ██╗ █████╗ ██╗██╗ ██╗ █████╗\n ██║ ██╔══██╗██║██║ ██╔╝██╔══██╗\n "
|
||||
" ██║ ███████║██║█████╔╝ ███████║\n ██║ ██╔══██║██║██╔═██╗ ██╔══██║\n "
|
||||
" ███████╗██║ ██║██║██║ ██╗██║ ██║\n ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝";
|
||||
|
||||
static int iniHandler(void* user, const char* section, const char* name, const char* value) {
|
||||
tShell_client *client = (tShell_client*)user;
|
||||
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
|
||||
static int iniHandler(void *user, const char *section, const char *name, const char *value)
|
||||
{
|
||||
tShell_client *client = (tShell_client *)user;
|
||||
|
||||
if (MATCH("auth", "public-key")) {
|
||||
shellC_loadKeys(client, value, NULL);
|
||||
PRINTINFO("Auth pubkey: %s\n", value);
|
||||
} else if (MATCH("auth", "private-key")){
|
||||
} else if (MATCH("auth", "private-key")) {
|
||||
shellC_loadKeys(client, NULL, value);
|
||||
} else {
|
||||
return 0; /* unknown section/name, error */
|
||||
return 0; /* unknown section/name, error */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool loadConfig(tShell_client *client, char *config) {
|
||||
#undef MATCH
|
||||
|
||||
bool loadConfig(tShell_client *client, char *config)
|
||||
{
|
||||
int iniRes;
|
||||
|
||||
printf("Loading config file '%s'...\n", config);
|
||||
if ((iniRes = ini_parse(config, iniHandler, (void*)client)) < 0) {
|
||||
if ((iniRes = ini_parse(config, iniHandler, (void *)client)) < 0) {
|
||||
switch (iniRes) {
|
||||
case -1: printf("Couldn't load config file '%s'!\n", config); break;
|
||||
case -2: printf("Memory allocation error :/\n"); break;
|
||||
default:
|
||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||
case -1:
|
||||
printf("Couldn't load config file '%s'!\n", config);
|
||||
break;
|
||||
case -2:
|
||||
printf("Memory allocation error :/\n");
|
||||
break;
|
||||
default:
|
||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -41,19 +54,26 @@ bool loadConfig(tShell_client *client, char *config) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argv, char *argc[]) {
|
||||
int main(int argv, char *argc[])
|
||||
{
|
||||
tShell_client client;
|
||||
char *configFile = "shell.ini";
|
||||
bool printPrompt = false;
|
||||
|
||||
shellT_printf("%s%s\n%s", shellT_getForeColor(TERM_BRIGHT_RED), LOGO, shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||
shellT_printf(" made with %s<3%s by CPunch - %s\n\nType 'help' for a list of commands\n\n", shellT_getForeColor(TERM_BRIGHT_RED), shellT_getForeColor(TERM_BRIGHT_WHITE), "v" MACROLITSTR(LAIKA_VERSION_MAJOR) "." MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT);
|
||||
shellT_printf("%s%s\n%s", shellT_getForeColor(TERM_BRIGHT_RED), LOGO,
|
||||
shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||
|
||||
shellT_printf(
|
||||
" made with %s<3%s by CPunch - %s\n\nType 'help' for a list of commands\n\n",
|
||||
shellT_getForeColor(TERM_BRIGHT_RED), shellT_getForeColor(TERM_BRIGHT_WHITE),
|
||||
"v" MACROLITSTR(LAIKA_VERSION_MAJOR) "."
|
||||
MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT);
|
||||
|
||||
shellC_init(&client);
|
||||
|
||||
/* load config file */
|
||||
if (argv >= 2)
|
||||
configFile = argc[1];
|
||||
configFile = argc[1];
|
||||
|
||||
if (!loadConfig(&client, configFile))
|
||||
return 1;
|
||||
@@ -61,7 +81,7 @@ int main(int argv, char *argc[]) {
|
||||
shellC_connectToCNC(&client, LAIKA_CNC_IP, LAIKA_CNC_PORT);
|
||||
|
||||
shellT_conioTerm();
|
||||
while(laikaS_isAlive((&client.peer->sock))) {
|
||||
while (laikaS_isAlive((&client.peer->sock))) {
|
||||
/* poll for 50ms */
|
||||
if (!shellC_poll(&client, 50)) {
|
||||
/* check if we have input! */
|
||||
|
||||
@@ -1,57 +1,63 @@
|
||||
#include "lmem.h"
|
||||
#include "sclient.h"
|
||||
|
||||
#include "lerror.h"
|
||||
#include "lmem.h"
|
||||
#include "lpacket.h"
|
||||
#include "lsodium.h"
|
||||
#include "sterm.h"
|
||||
|
||||
#include "sclient.h"
|
||||
|
||||
|
||||
void shell_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
|
||||
tShell_client *client = (tShell_client*)uData;
|
||||
void shell_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
|
||||
void *uData)
|
||||
{
|
||||
tShell_client *client = (tShell_client *)uData;
|
||||
|
||||
laikaS_emptyOutPacket(client->peer, LAIKAPKT_PINGPONG);
|
||||
}
|
||||
|
||||
/* ======================================[[ PeerHashMap ]]====================================== */
|
||||
|
||||
typedef struct sShell_hashMapElem {
|
||||
typedef struct sShell_hashMapElem
|
||||
{
|
||||
int id;
|
||||
tShell_peer *peer;
|
||||
uint8_t *pub;
|
||||
} tShell_hashMapElem;
|
||||
|
||||
int shell_ElemCompare(const void *a, const void *b, void *udata) {
|
||||
int shell_ElemCompare(const void *a, const void *b, void *udata)
|
||||
{
|
||||
const tShell_hashMapElem *ua = a;
|
||||
const tShell_hashMapElem *ub = b;
|
||||
|
||||
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
||||
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
uint64_t shell_ElemHash(const void *item, uint64_t seed0, uint64_t seed1) {
|
||||
uint64_t shell_ElemHash(const void *item, uint64_t seed0, uint64_t seed1)
|
||||
{
|
||||
const tShell_hashMapElem *u = item;
|
||||
return *(uint64_t*)(u->pub); /* hashes pub key (first 8 bytes) */
|
||||
return *(uint64_t *)(u->pub); /* hashes pub key (first 8 bytes) */
|
||||
}
|
||||
|
||||
/* ====================================[[ Packet Handlers ]]==================================== */
|
||||
|
||||
void shellC_handleHandshakeRes(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handleHandshakeRes(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
uint8_t endianness = laikaS_readByte(&peer->sock);
|
||||
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
||||
|
||||
PRINTSUCC("Handshake accepted!\n");
|
||||
}
|
||||
|
||||
void shellC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
LAIKA_DEBUG("got ping from cnc!\n");
|
||||
/* stubbed */
|
||||
}
|
||||
|
||||
|
||||
void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
||||
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
||||
tShell_client *client = (tShell_client*)uData;
|
||||
tShell_client *client = (tShell_client *)uData;
|
||||
tShell_peer *bot;
|
||||
uint8_t type, osType;
|
||||
|
||||
@@ -78,9 +84,10 @@ void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
|
||||
shellC_addPeer(client, bot);
|
||||
}
|
||||
|
||||
void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
||||
tShell_client *client = (tShell_client*)uData;
|
||||
tShell_client *client = (tShell_client *)uData;
|
||||
tShell_peer *bot;
|
||||
uint8_t type;
|
||||
int id;
|
||||
@@ -100,17 +107,19 @@ void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
|
||||
shellC_rmvPeer(client, bot, id);
|
||||
}
|
||||
|
||||
void shellC_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
/* stubbed! this packet is a no-op currently */
|
||||
}
|
||||
|
||||
void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||
tShell_client *client = (tShell_client*)uData;
|
||||
tShell_client *client = (tShell_client *)uData;
|
||||
uint32_t id;
|
||||
|
||||
/* ignore packet if malformed */
|
||||
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
||||
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH + sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
||||
return;
|
||||
|
||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
||||
@@ -124,8 +133,9 @@ void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
|
||||
shellT_writeRawOutput(buf, sz);
|
||||
}
|
||||
|
||||
void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
||||
tShell_client *client = (tShell_client*)uData;
|
||||
void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||
{
|
||||
tShell_client *client = (tShell_client *)uData;
|
||||
uint32_t id;
|
||||
|
||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
||||
@@ -176,26 +186,24 @@ struct sLaika_peerPacketInfo shellC_pktTbl[LAIKAPKT_MAXNONE] = {
|
||||
/* clang-format on */
|
||||
|
||||
/* socket event */
|
||||
void shellC_onPollFail(struct sLaika_socket *sock, void *uData) {
|
||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
||||
struct sShell_client *client = (struct sShell_client*)uData;
|
||||
void shellC_onPollFail(struct sLaika_socket *sock, void *uData)
|
||||
{
|
||||
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||
struct sShell_client *client = (struct sShell_client *)uData;
|
||||
|
||||
laikaS_kill(&client->peer->sock);
|
||||
}
|
||||
|
||||
/* ======================================[[ Client API ]]======================================= */
|
||||
|
||||
void shellC_init(tShell_client *client) {
|
||||
void shellC_init(tShell_client *client)
|
||||
{
|
||||
laikaP_initPList(&client->pList);
|
||||
client->peer = laikaS_newPeer(
|
||||
shellC_pktTbl,
|
||||
&client->pList,
|
||||
shellC_onPollFail,
|
||||
(void*)client,
|
||||
(void*)client
|
||||
);
|
||||
client->peer = laikaS_newPeer(shellC_pktTbl, &client->pList, shellC_onPollFail, (void *)client,
|
||||
(void *)client);
|
||||
|
||||
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash, shell_ElemCompare, NULL, NULL);
|
||||
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash,
|
||||
shell_ElemCompare, NULL, NULL);
|
||||
client->openShell = NULL;
|
||||
client->peerTbl = NULL;
|
||||
client->peerTblCap = 4;
|
||||
@@ -223,7 +231,8 @@ void shellC_init(tShell_client *client) {
|
||||
}
|
||||
}
|
||||
|
||||
void shellC_cleanup(tShell_client *client) {
|
||||
void shellC_cleanup(tShell_client *client)
|
||||
{
|
||||
int i;
|
||||
|
||||
laikaS_freePeer(client->peer);
|
||||
@@ -240,13 +249,15 @@ void shellC_cleanup(tShell_client *client) {
|
||||
laikaM_free(client->peerTbl);
|
||||
}
|
||||
|
||||
void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
||||
void shellC_connectToCNC(tShell_client *client, char *ip, char *port)
|
||||
{
|
||||
struct sLaika_socket *sock = &client->peer->sock;
|
||||
|
||||
PRINTINFO("Connecting to %s:%s...\n", ip, port);
|
||||
|
||||
/* create encryption keys */
|
||||
if (crypto_kx_client_session_keys(client->peer->inKey, client->peer->outKey, client->pub, client->priv, client->peer->peerPub) != 0)
|
||||
if (crypto_kx_client_session_keys(client->peer->inKey, client->peer->outKey, client->pub,
|
||||
client->priv, client->peer->peerPub) != 0)
|
||||
LAIKA_ERROR("failed to gen session key!\n");
|
||||
|
||||
/* setup socket */
|
||||
@@ -262,7 +273,8 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
||||
laikaS_writeByte(sock, LAIKA_OSTYPE);
|
||||
laikaS_write(sock, client->pub, sizeof(client->pub)); /* write public key */
|
||||
|
||||
/* write stub hostname & ip str (since we're a panel/dummy client, cnc doesn't need this information really) */
|
||||
/* write stub hostname & ip str (since we're a panel/dummy client, cnc doesn't need this
|
||||
* information really) */
|
||||
laikaS_zeroWrite(sock, LAIKA_HOSTNAME_LEN);
|
||||
laikaS_zeroWrite(sock, LAIKA_INET_LEN);
|
||||
laikaS_endOutPacket(client->peer);
|
||||
@@ -276,7 +288,8 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
||||
/* the handshake requests will be sent on the next call to shellC_poll */
|
||||
}
|
||||
|
||||
bool shellC_poll(tShell_client *client, int timeout) {
|
||||
bool shellC_poll(tShell_client *client, int timeout)
|
||||
{
|
||||
struct sLaika_pollEvent *evnts;
|
||||
int numEvents, i;
|
||||
|
||||
@@ -299,15 +312,18 @@ bool shellC_poll(tShell_client *client, int timeout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv) {
|
||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv)
|
||||
{
|
||||
if (!laikaK_loadKeys(pub ? client->pub : NULL, priv ? client->priv : NULL, pub, priv)) {
|
||||
shellC_cleanup(client);
|
||||
LAIKA_ERROR("Failed to init keypair!\n");
|
||||
}
|
||||
}
|
||||
|
||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id) {
|
||||
tShell_hashMapElem *elem = (tShell_hashMapElem*)hashmap_get(client->peers, &(tShell_hashMapElem){.pub = pub});
|
||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id)
|
||||
{
|
||||
tShell_hashMapElem *elem =
|
||||
(tShell_hashMapElem *)hashmap_get(client->peers, &(tShell_hashMapElem){.pub = pub});
|
||||
|
||||
/* return peer if elem was found, otherwise return NULL */
|
||||
if (elem) {
|
||||
@@ -319,7 +335,8 @@ tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id) {
|
||||
}
|
||||
}
|
||||
|
||||
int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
||||
int shellC_addPeer(tShell_client *client, tShell_peer *newPeer)
|
||||
{
|
||||
/* find empty ID */
|
||||
int id;
|
||||
for (id = 0; id < client->peerTblCount; id++) {
|
||||
@@ -329,7 +346,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
||||
|
||||
/* if we didn't find an empty id, grow the array */
|
||||
if (id == client->peerTblCount) {
|
||||
laikaM_growarray(tShell_peer*, client->peerTbl, 1, client->peerTblCount, client->peerTblCap);
|
||||
laikaM_growarray(tShell_peer *, client->peerTbl, 1, client->peerTblCount,
|
||||
client->peerTblCap);
|
||||
client->peerTblCount++;
|
||||
}
|
||||
|
||||
@@ -337,7 +355,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
||||
client->peerTbl[id] = newPeer;
|
||||
|
||||
/* insert into hashmap */
|
||||
hashmap_set(client->peers, &(tShell_hashMapElem){.id = id, .pub = newPeer->pub, .peer = newPeer});
|
||||
hashmap_set(client->peers,
|
||||
&(tShell_hashMapElem){.id = id, .pub = newPeer->pub, .peer = newPeer});
|
||||
|
||||
/* let user know */
|
||||
if (!shellC_isShellOpen(client)) {
|
||||
@@ -347,7 +366,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
||||
return id;
|
||||
}
|
||||
|
||||
void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id) {
|
||||
void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id)
|
||||
{
|
||||
/* remove from bot tbl */
|
||||
client->peerTbl[id] = NULL;
|
||||
|
||||
@@ -363,7 +383,8 @@ void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id) {
|
||||
shellP_freePeer(oldPeer);
|
||||
}
|
||||
|
||||
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row) {
|
||||
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row)
|
||||
{
|
||||
/* check if we already have a shell open */
|
||||
if (client->openShell)
|
||||
return;
|
||||
@@ -377,7 +398,8 @@ void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, ui
|
||||
client->openShell = peer;
|
||||
}
|
||||
|
||||
void shellC_closeShell(tShell_client *client) {
|
||||
void shellC_closeShell(tShell_client *client)
|
||||
{
|
||||
uint32_t id = 0; /* we will *ALWAYS* only have one shell open */
|
||||
/* check if we have a shell open */
|
||||
if (!shellC_isShellOpen(client))
|
||||
@@ -391,7 +413,8 @@ void shellC_closeShell(tShell_client *client) {
|
||||
client->openShell = NULL;
|
||||
}
|
||||
|
||||
void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz) {
|
||||
void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz)
|
||||
{
|
||||
uint32_t i, id = 0; /* we will *ALWAYS* only have one shell open */
|
||||
struct sLaika_socket *sock = &client->peer->sock;
|
||||
/* check if we have a shell open */
|
||||
@@ -401,21 +424,22 @@ void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz) {
|
||||
laikaS_startVarPacket(client->peer, LAIKAPKT_SHELL_DATA);
|
||||
laikaS_writeInt(sock, &id, sizeof(uint32_t));
|
||||
switch (client->openShell->osType) {
|
||||
case LAIKA_OSTYPE: /* if we're the same as the target OS, line endings don't need to be converted! */
|
||||
laikaS_write(sock, data, sz);
|
||||
break;
|
||||
default:
|
||||
/* line endings have to be converted (ALWAYS LINUX->WIN for now) */
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (data[i] == '\n') {
|
||||
/* convert to windows line endings */
|
||||
laikaS_writeByte(sock, '\r');
|
||||
laikaS_writeByte(sock, '\n');
|
||||
} else {
|
||||
laikaS_writeByte(sock, data[i]);
|
||||
}
|
||||
case LAIKA_OSTYPE: /* if we're the same as the target OS, line endings don't need to be
|
||||
converted! */
|
||||
laikaS_write(sock, data, sz);
|
||||
break;
|
||||
default:
|
||||
/* line endings have to be converted (ALWAYS LINUX->WIN for now) */
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (data[i] == '\n') {
|
||||
/* convert to windows line endings */
|
||||
laikaS_writeByte(sock, '\r');
|
||||
laikaS_writeByte(sock, '\n');
|
||||
} else {
|
||||
laikaS_writeByte(sock, data[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
laikaS_endVarPacket(client->peer);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
#include <setjmp.h>
|
||||
#include "scmd.h"
|
||||
|
||||
#include "lerror.h"
|
||||
#include "lmem.h"
|
||||
#include "sclient.h"
|
||||
#include "speer.h"
|
||||
#include "scmd.h"
|
||||
#include "sterm.h"
|
||||
#include "lerror.h"
|
||||
|
||||
#define CMD_ERROR(...) do { \
|
||||
PRINTTAG(TERM_BRIGHT_RED); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
longjmp(cmdE_err, 1); \
|
||||
} while(0);
|
||||
#include <setjmp.h>
|
||||
|
||||
#define CMD_ERROR(...) \
|
||||
do { \
|
||||
PRINTTAG(TERM_BRIGHT_RED); \
|
||||
shellT_printf(__VA_ARGS__); \
|
||||
longjmp(cmdE_err, 1); \
|
||||
} while (0);
|
||||
|
||||
jmp_buf cmdE_err;
|
||||
|
||||
@@ -19,14 +21,16 @@ jmp_buf cmdE_err;
|
||||
|
||||
tShell_cmdDef *shellS_findCmd(char *cmd);
|
||||
|
||||
tShell_peer *shellS_getPeer(tShell_client *client, int id) {
|
||||
tShell_peer *shellS_getPeer(tShell_client *client, int id)
|
||||
{
|
||||
if (id < 0 || id >= client->peerTblCount || client->peerTbl[id] == NULL)
|
||||
CMD_ERROR("Not a valid peer ID! [%d]\n", id);
|
||||
|
||||
return client->peerTbl[id];
|
||||
}
|
||||
|
||||
int shellS_readInt(char *str) {
|
||||
int shellS_readInt(char *str)
|
||||
{
|
||||
return atoi(str);
|
||||
}
|
||||
|
||||
@@ -34,12 +38,14 @@ int shellS_readInt(char *str) {
|
||||
|
||||
void helpCMD(tShell_client *client, int argc, char *argv[]);
|
||||
|
||||
void quitCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
void quitCMD(tShell_client *client, int argc, char *argv[])
|
||||
{
|
||||
PRINTINFO("Killing socket...\n");
|
||||
laikaS_kill(&client->peer->sock);
|
||||
}
|
||||
|
||||
void listPeersCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
void listPeersCMD(tShell_client *client, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < client->peerTblCount; i++) {
|
||||
@@ -50,7 +56,8 @@ void listPeersCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
void infoCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
void infoCMD(tShell_client *client, int argc, char *argv[])
|
||||
{
|
||||
tShell_peer *peer;
|
||||
int id;
|
||||
|
||||
@@ -65,7 +72,8 @@ void infoCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
shellP_printInfo(peer);
|
||||
}
|
||||
|
||||
void openShellCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
void openShellCMD(tShell_client *client, int argc, char *argv[])
|
||||
{
|
||||
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||
tShell_peer *peer;
|
||||
int id, sz, cols, rows;
|
||||
@@ -112,7 +120,8 @@ void openShellCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
|
||||
/* =====================================[[ Command Table ]]===================================== */
|
||||
|
||||
#define CREATECMD(_cmd, _syntax, _help, _callback) ((tShell_cmdDef){.cmd = _cmd, .syntax = _syntax, .help = _help, .callback = _callback})
|
||||
#define CREATECMD(_cmd, _syntax, _help, _callback) \
|
||||
((tShell_cmdDef){.cmd = _cmd, .syntax = _syntax, .help = _help, .callback = _callback})
|
||||
|
||||
tShell_cmdDef shellS_cmds[] = {
|
||||
CREATECMD("help", "help", "Lists avaliable commands", helpCMD),
|
||||
@@ -124,11 +133,12 @@ tShell_cmdDef shellS_cmds[] = {
|
||||
|
||||
#undef CREATECMD
|
||||
|
||||
tShell_cmdDef *shellS_findCmd(char *cmd) {
|
||||
tShell_cmdDef *shellS_findCmd(char *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* TODO: make a hashmap for command lookup */
|
||||
for (i = 0; i < (sizeof(shellS_cmds)/sizeof(tShell_cmdDef)); i++) {
|
||||
for (i = 0; i < (sizeof(shellS_cmds) / sizeof(tShell_cmdDef)); i++) {
|
||||
if (strcmp(shellS_cmds[i].cmd, cmd) == 0)
|
||||
return &shellS_cmds[i]; /* cmd found */
|
||||
}
|
||||
@@ -136,24 +146,32 @@ tShell_cmdDef *shellS_findCmd(char *cmd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void helpCMD(tShell_client *client, int argc, char *argv[]) {
|
||||
void helpCMD(tShell_client *client, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
shellT_printf("======= [[ %sCommand List%s ]] =======\n", shellT_getForeColor(TERM_BRIGHT_YELLOW), shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||
for (i = 0; i < (sizeof(shellS_cmds)/sizeof(tShell_cmdDef)); i++) {
|
||||
shellT_printf("'%s%s%s'\t- %s\n", shellT_getForeColor(TERM_BRIGHT_YELLOW), shellS_cmds[i].syntax, shellT_getForeColor(TERM_BRIGHT_WHITE), shellS_cmds[i].help);
|
||||
shellT_printf("======= [[ %sCommand List%s ]] =======\n",
|
||||
shellT_getForeColor(TERM_BRIGHT_YELLOW), shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||
|
||||
for (i = 0; i < (sizeof(shellS_cmds) / sizeof(tShell_cmdDef)); i++) {
|
||||
shellT_printf("'%s%s%s'\t- %s\n", shellT_getForeColor(TERM_BRIGHT_YELLOW),
|
||||
shellS_cmds[i].syntax, shellT_getForeColor(TERM_BRIGHT_WHITE),
|
||||
shellS_cmds[i].help);
|
||||
}
|
||||
}
|
||||
|
||||
void shellS_initCmds(void) {
|
||||
void shellS_initCmds(void)
|
||||
{
|
||||
/* stubbed for now, TODO: setup command hashmap */
|
||||
}
|
||||
|
||||
void shellS_cleanupCmds(void) {
|
||||
void shellS_cleanupCmds(void)
|
||||
{
|
||||
/* stubbed for now, TODO: free command hashmap */
|
||||
}
|
||||
|
||||
char **shellS_splitCmd(char *cmd, int *argSize) {
|
||||
char **shellS_splitCmd(char *cmd, int *argSize)
|
||||
{
|
||||
int argCount = 0;
|
||||
int argCap = 4;
|
||||
char *temp;
|
||||
@@ -165,7 +183,7 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
||||
if (arg != cmd) {
|
||||
if (arg[-1] == '\\') { /* space is part of the argument */
|
||||
/* remove the '\' character */
|
||||
for (temp = arg-1; *temp != '\0'; temp++) {
|
||||
for (temp = arg - 1; *temp != '\0'; temp++) {
|
||||
temp[0] = temp[1];
|
||||
}
|
||||
arg++;
|
||||
@@ -175,7 +193,7 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
||||
}
|
||||
|
||||
/* insert into our 'args' array */
|
||||
laikaM_growarray(char*, args, 1, argCount, argCap);
|
||||
laikaM_growarray(char *, args, 1, argCount, argCap);
|
||||
args[argCount++] = arg;
|
||||
} while ((arg = strchr(arg, ' ')) != NULL); /* while we still have a delimiter */
|
||||
|
||||
@@ -183,7 +201,8 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
||||
return args;
|
||||
}
|
||||
|
||||
void shellS_runCmd(tShell_client *client, char *cmd) {
|
||||
void shellS_runCmd(tShell_client *client, char *cmd)
|
||||
{
|
||||
tShell_cmdDef *cmdDef;
|
||||
char **argc;
|
||||
int args;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "speer.h"
|
||||
|
||||
#include "lmem.h"
|
||||
#include "lpacket.h"
|
||||
#include "speer.h"
|
||||
#include "sterm.h"
|
||||
|
||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char *hostname, char *inet, char *ipStr) {
|
||||
tShell_peer *peer = (tShell_peer*)laikaM_malloc(sizeof(tShell_peer));
|
||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char *hostname,
|
||||
char *inet, char *ipStr)
|
||||
{
|
||||
tShell_peer *peer = (tShell_peer *)laikaM_malloc(sizeof(tShell_peer));
|
||||
peer->type = type;
|
||||
peer->osType = osType;
|
||||
|
||||
@@ -17,37 +20,50 @@ tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char
|
||||
memcpy(peer->ipStr, ipStr, LAIKA_IPSTR_LEN);
|
||||
|
||||
/* restore NULL terminators */
|
||||
peer->hostname[LAIKA_HOSTNAME_LEN-1] = '\0';
|
||||
peer->inet[LAIKA_INET_LEN-1] = '\0';
|
||||
peer->ipStr[LAIKA_IPSTR_LEN-1] = '\0';
|
||||
peer->hostname[LAIKA_HOSTNAME_LEN - 1] = '\0';
|
||||
peer->inet[LAIKA_INET_LEN - 1] = '\0';
|
||||
peer->ipStr[LAIKA_IPSTR_LEN - 1] = '\0';
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
void shellP_freePeer(tShell_peer *peer) {
|
||||
void shellP_freePeer(tShell_peer *peer)
|
||||
{
|
||||
laikaM_free(peer);
|
||||
}
|
||||
|
||||
char *shellP_typeStr(tShell_peer *peer) {
|
||||
char *shellP_typeStr(tShell_peer *peer)
|
||||
{
|
||||
switch (peer->type) {
|
||||
case PEER_BOT: return "Bot";
|
||||
case PEER_CNC: return "CNC";
|
||||
case PEER_AUTH: return "Auth";
|
||||
default: return "err";
|
||||
case PEER_BOT:
|
||||
return "Bot";
|
||||
case PEER_CNC:
|
||||
return "CNC";
|
||||
case PEER_AUTH:
|
||||
return "Auth";
|
||||
default:
|
||||
return "err";
|
||||
}
|
||||
}
|
||||
|
||||
char *shellP_osTypeStr(tShell_peer *peer) {
|
||||
char *shellP_osTypeStr(tShell_peer *peer)
|
||||
{
|
||||
switch (peer->osType) {
|
||||
case OS_WIN: return "Windows";
|
||||
case OS_LIN: return "Linux";
|
||||
default: return "unkn";
|
||||
case OS_WIN:
|
||||
return "Windows";
|
||||
case OS_LIN:
|
||||
return "Linux";
|
||||
default:
|
||||
return "unkn";
|
||||
}
|
||||
}
|
||||
|
||||
void shellP_printInfo(tShell_peer *peer) {
|
||||
char buf[128]; /* i don't expect bin2hex to write outside this, but it's only user-info and doesn't break anything (ie doesn't write outside the buffer) */
|
||||
void shellP_printInfo(tShell_peer *peer)
|
||||
{
|
||||
char buf[128]; /* i don't expect bin2hex to write outside this, but it's only user-info and
|
||||
doesn't break anything (ie doesn't write outside the buffer) */
|
||||
|
||||
sodium_bin2hex(buf, sizeof(buf), peer->pub, crypto_kx_PUBLICKEYBYTES);
|
||||
shellT_printf("\t%s-%s\n\tOS: %s\n\tINET: %s\n\tPUBKEY: %s\n", peer->ipStr, peer->hostname, shellP_osTypeStr(peer), peer->inet, buf);
|
||||
shellT_printf("\t%s-%s\n\tOS: %s\n\tINET: %s\n\tPUBKEY: %s\n", peer->ipStr, peer->hostname,
|
||||
shellP_osTypeStr(peer), peer->inet, buf);
|
||||
}
|
||||
@@ -1,24 +1,26 @@
|
||||
#include "lmem.h"
|
||||
#include "scmd.h"
|
||||
#include "sterm.h"
|
||||
|
||||
#define KEY_ESCAPE 0x001b
|
||||
#define KEY_ENTER 0x000a
|
||||
#define KEY_BACKSPACE 0x007f
|
||||
#define KEY_UP 0x0105
|
||||
#define KEY_DOWN 0x0106
|
||||
#define KEY_LEFT 0x0107
|
||||
#define KEY_RIGHT 0x0108
|
||||
#include "lmem.h"
|
||||
#include "scmd.h"
|
||||
|
||||
#define cursorForward(x) printf("\033[%dC", (x))
|
||||
#define KEY_ESCAPE 0x001b
|
||||
#define KEY_ENTER 0x000a
|
||||
#define KEY_BACKSPACE 0x007f
|
||||
#define KEY_UP 0x0105
|
||||
#define KEY_DOWN 0x0106
|
||||
#define KEY_LEFT 0x0107
|
||||
#define KEY_RIGHT 0x0108
|
||||
|
||||
#define cursorForward(x) printf("\033[%dC", (x))
|
||||
#define cursorBackward(x) printf("\033[%dD", (x))
|
||||
#define clearLine() printf("\033[2K")
|
||||
#define clearLine() printf("\033[2K")
|
||||
|
||||
struct termios orig_termios;
|
||||
char *cmd, *prompt = "$> ";
|
||||
int cmdCount = 0, cmdCap = 4, cmdCursor = 0;
|
||||
|
||||
void shellT_conioTerm(void) {
|
||||
void shellT_conioTerm(void)
|
||||
{
|
||||
struct termios new_termios;
|
||||
|
||||
/* take two copies - one for now, one for later */
|
||||
@@ -31,43 +33,80 @@ void shellT_conioTerm(void) {
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
||||
}
|
||||
|
||||
void shellT_resetTerm(void) {
|
||||
void shellT_resetTerm(void)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
|
||||
}
|
||||
|
||||
const char *shellT_getForeColor(TERM_COLOR col) {
|
||||
const char *shellT_getForeColor(TERM_COLOR col)
|
||||
{
|
||||
switch (col) {
|
||||
case TERM_BLACK: return "\033[30m"; break;
|
||||
case TERM_RED: return "\033[31m"; break;
|
||||
case TERM_GREEN: return "\033[32m"; break;
|
||||
case TERM_YELLOW: return "\033[33m"; break;
|
||||
case TERM_BLUE: return "\033[34m"; break;
|
||||
case TERM_MAGENTA: return "\033[35m"; break;
|
||||
case TERM_CYAN: return "\033[36m"; break;
|
||||
case TERM_WHITE: return "\033[37m"; break;
|
||||
case TERM_BRIGHT_BLACK: return "\033[90m"; break;
|
||||
case TERM_BRIGHT_RED: return "\033[91m"; break;
|
||||
case TERM_BRIGHT_GREEN: return "\033[92m"; break;
|
||||
case TERM_BRIGHT_YELLOW: return "\033[93m"; break;
|
||||
case TERM_BRIGHT_BLUE: return "\033[94m"; break;
|
||||
case TERM_BRIGHT_MAGENTA: return "\033[95m"; break;
|
||||
case TERM_BRIGHT_CYAN: return "\033[96m"; break;
|
||||
case TERM_BRIGHT_WHITE: default: return "\033[97m"; break;
|
||||
case TERM_BLACK:
|
||||
return "\033[30m";
|
||||
break;
|
||||
case TERM_RED:
|
||||
return "\033[31m";
|
||||
break;
|
||||
case TERM_GREEN:
|
||||
return "\033[32m";
|
||||
break;
|
||||
case TERM_YELLOW:
|
||||
return "\033[33m";
|
||||
break;
|
||||
case TERM_BLUE:
|
||||
return "\033[34m";
|
||||
break;
|
||||
case TERM_MAGENTA:
|
||||
return "\033[35m";
|
||||
break;
|
||||
case TERM_CYAN:
|
||||
return "\033[36m";
|
||||
break;
|
||||
case TERM_WHITE:
|
||||
return "\033[37m";
|
||||
break;
|
||||
case TERM_BRIGHT_BLACK:
|
||||
return "\033[90m";
|
||||
break;
|
||||
case TERM_BRIGHT_RED:
|
||||
return "\033[91m";
|
||||
break;
|
||||
case TERM_BRIGHT_GREEN:
|
||||
return "\033[92m";
|
||||
break;
|
||||
case TERM_BRIGHT_YELLOW:
|
||||
return "\033[93m";
|
||||
break;
|
||||
case TERM_BRIGHT_BLUE:
|
||||
return "\033[94m";
|
||||
break;
|
||||
case TERM_BRIGHT_MAGENTA:
|
||||
return "\033[95m";
|
||||
break;
|
||||
case TERM_BRIGHT_CYAN:
|
||||
return "\033[96m";
|
||||
break;
|
||||
case TERM_BRIGHT_WHITE:
|
||||
default:
|
||||
return "\033[97m";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void shellT_printf(const char *format, ...) {
|
||||
void shellT_printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* waits for input for timeout. returns true if input is ready to be read, false if no events */
|
||||
bool shellT_waitForInput(int timeout) {
|
||||
bool shellT_waitForInput(int timeout)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
@@ -81,16 +120,19 @@ bool shellT_waitForInput(int timeout) {
|
||||
return select(1, &fds, NULL, NULL, &tv) > 0;
|
||||
}
|
||||
|
||||
int shellT_readRawInput(uint8_t *buf, size_t max) {
|
||||
int shellT_readRawInput(uint8_t *buf, size_t max)
|
||||
{
|
||||
return read(STDIN_FILENO, buf, max);
|
||||
}
|
||||
|
||||
void shellT_writeRawOutput(uint8_t *buf, size_t sz) {
|
||||
void shellT_writeRawOutput(uint8_t *buf, size_t sz)
|
||||
{
|
||||
write(STDOUT_FILENO, buf, sz);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void shellT_getTermSize(int *col, int *row) {
|
||||
void shellT_getTermSize(int *col, int *row)
|
||||
{
|
||||
struct winsize ws;
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
||||
|
||||
@@ -98,18 +140,20 @@ void shellT_getTermSize(int *col, int *row) {
|
||||
*row = ws.ws_row;
|
||||
}
|
||||
|
||||
char shellT_getch(void) {
|
||||
char shellT_getch(void)
|
||||
{
|
||||
int r;
|
||||
char in;
|
||||
|
||||
if ((r = shellT_readRawInput((uint8_t*)&in, 1)) > 0) {
|
||||
if ((r = shellT_readRawInput((uint8_t *)&in, 1)) > 0) {
|
||||
return in;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int shellT_kbesc(void) {
|
||||
int shellT_kbesc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* if no event waiting, it's KEY_ESCAPE */
|
||||
@@ -118,11 +162,21 @@ int shellT_kbesc(void) {
|
||||
|
||||
if ((c = shellT_getch()) == '[') {
|
||||
switch (shellT_getch()) {
|
||||
case 'A': c = KEY_UP; break;
|
||||
case 'B': c = KEY_DOWN; break;
|
||||
case 'C': c = KEY_RIGHT; break;
|
||||
case 'D': c = KEY_LEFT; break;
|
||||
default: c = 0; break;
|
||||
case 'A':
|
||||
c = KEY_UP;
|
||||
break;
|
||||
case 'B':
|
||||
c = KEY_DOWN;
|
||||
break;
|
||||
case 'C':
|
||||
c = KEY_RIGHT;
|
||||
break;
|
||||
case 'D':
|
||||
c = KEY_LEFT;
|
||||
break;
|
||||
default:
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
c = 0;
|
||||
@@ -130,76 +184,85 @@ int shellT_kbesc(void) {
|
||||
|
||||
/* unrecognized key? consume until there's no event */
|
||||
if (c == 0) {
|
||||
while (shellT_waitForInput(0)) shellT_getch();
|
||||
while (shellT_waitForInput(0))
|
||||
shellT_getch();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int shellT_kbget(void) {
|
||||
int shellT_kbget(void)
|
||||
{
|
||||
char c = shellT_getch();
|
||||
return (c == KEY_ESCAPE) ? shellT_kbesc() : c;
|
||||
}
|
||||
|
||||
void shellT_printPrompt(void) {
|
||||
void shellT_printPrompt(void)
|
||||
{
|
||||
clearLine();
|
||||
shellT_printf("\r%s%.*s", prompt, cmdCount, (cmd ? cmd : ""));
|
||||
if (cmdCount > cmdCursor)
|
||||
cursorBackward(cmdCount-cmdCursor);
|
||||
cursorBackward(cmdCount - cmdCursor);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void shellT_setPrompt(char *_prompt) {
|
||||
void shellT_setPrompt(char *_prompt)
|
||||
{
|
||||
prompt = _prompt;
|
||||
}
|
||||
|
||||
bool isAscii(int c) {
|
||||
return c >= ' ' && c <= '~'; /* covers every non-controller related ascii characters (ignoring the extended character range) */
|
||||
/* covers every non-controller related ascii characters (ignoring the extended character range) */
|
||||
bool isAscii(int c)
|
||||
{
|
||||
return c >= ' ' && c <= '~';
|
||||
}
|
||||
|
||||
void shellT_addChar(tShell_client *client, int c) {
|
||||
void shellT_addChar(tShell_client *client, int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (c) {
|
||||
case KEY_BACKSPACE:
|
||||
if (cmdCursor > 0) {
|
||||
laikaM_rmvarray(cmd, cmdCount, (cmdCursor-1), 1);
|
||||
cmdCursor--;
|
||||
shellT_printPrompt();
|
||||
}
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if (cmdCursor > 0) {
|
||||
cursorBackward(1);
|
||||
--cmdCursor;
|
||||
fflush(stdout);
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
if (cmdCursor < cmdCount) {
|
||||
cursorForward(1);
|
||||
cmdCursor++;
|
||||
fflush(stdout);
|
||||
}
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
if (cmdCount > 0) {
|
||||
cmd[cmdCount] = '\0';
|
||||
cmdCount = 0;
|
||||
cmdCursor = 0;
|
||||
shellS_runCmd(client, cmd);
|
||||
shellT_printPrompt();
|
||||
}
|
||||
break;
|
||||
case KEY_UP: case KEY_DOWN: break; /* ignore these */
|
||||
default:
|
||||
/* we only want to accept valid input, just ignore non-ascii characters */
|
||||
if (!isAscii(c))
|
||||
return;
|
||||
|
||||
laikaM_growarray(char, cmd, 1, cmdCount, cmdCap);
|
||||
laikaM_insertarray(cmd, cmdCount, cmdCursor, 1);
|
||||
cmd[cmdCursor++] = c;
|
||||
case KEY_BACKSPACE:
|
||||
if (cmdCursor > 0) {
|
||||
laikaM_rmvarray(cmd, cmdCount, (cmdCursor - 1), 1);
|
||||
cmdCursor--;
|
||||
shellT_printPrompt();
|
||||
}
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if (cmdCursor > 0) {
|
||||
cursorBackward(1);
|
||||
--cmdCursor;
|
||||
fflush(stdout);
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
if (cmdCursor < cmdCount) {
|
||||
cursorForward(1);
|
||||
cmdCursor++;
|
||||
fflush(stdout);
|
||||
}
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
if (cmdCount > 0) {
|
||||
cmd[cmdCount] = '\0';
|
||||
cmdCount = 0;
|
||||
cmdCursor = 0;
|
||||
shellS_runCmd(client, cmd);
|
||||
shellT_printPrompt();
|
||||
}
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
break; /* ignore these */
|
||||
default:
|
||||
/* we only want to accept valid input, just ignore non-ascii characters */
|
||||
if (!isAscii(c))
|
||||
return;
|
||||
|
||||
laikaM_growarray(char, cmd, 1, cmdCount, cmdCap);
|
||||
laikaM_insertarray(cmd, cmdCount, cmdCursor, 1);
|
||||
cmd[cmdCursor++] = c;
|
||||
shellT_printPrompt();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user