BitLab 0.1.0
BitLab: A Browser for the Bitcoin P2P Network and Blockchain
Loading...
Searching...
No Matches
cli.h File Reference
#include <stdio.h>
#include <stdlib.h>

Go to the source code of this file.

Data Structures

struct  cli_command
 CLI command structure. More...
 

Macros

#define MAX_LINE_LEN   256
 
#define CLI_BUFSIZE   64
 
#define CLI_DELIM   " "
 
#define CLI_COMMANDS_NUM   (int) (sizeof(cli_commands) / sizeof(cli_command))
 
#define CLI_HISTORY_FILE   "cli_history.txt"
 
#define CLI_PREFIX   "BitLab> "
 

Functions

void print_help ()
 Prints CLI command help.
 
void print_usage (const char *command_name)
 Prints CLI command usage.
 
void print_commands ()
 Prints CLI commands.
 
const char * create_history_dir ()
 Create history directory.
 
int cli_exit (char **args)
 Exits BitLab CLI command.
 
int cli_history (char **args)
 Prints CLI command history.
 
int cli_echo (char **args)
 Echoes the input.
 
int cli_whoami (char **args)
 Prints the user name.
 
int cli_get_ip (char **args)
 Gets remote IP address on an URL or host machine if no URL is provided.
 
int cli_info (char **args)
 Prints program information.
 
int cli_peer_discovery (char **args)
 Discovers Bitcoin peers.
 
int cli_clear (char **args)
 Clears CLI window.
 
int cli_help (char **args)
 Prints CLI command help.
 
int cli_ping (char **args)
 Pings the specified IP address.
 
int cli_connect (char **args)
 Connects to the specified IP address.
 
int cli_list (char **args)
 Lists all connected nodes.
 
int cli_getaddr (char **args)
 Sends a 'getaddr' message to the specified peer.
 
int cli_disconnect (char **args)
 Disconnects from the specified node.
 
int cli_getheaders (char **args)
 Sends a 'getheaders' message to specified peer.
 
int cli_getblocks (char **args)
 Sends a 'getblocks' message to specified peer.
 
int cli_inv (char **args)
 Sends a 'inv' message to specified peer.
 
int cli_getdata (char **args)
 Sends a 'getdata' message to specified peer.
 
int cli_tx (char **args)
 Sends a 'tx' message to specified peer.
 
int cli_get_line (char **lineptr, size_t *n, FILE *stream)
 Gets the line from the file stream.
 
char * cli_read_line (void)
 Reads input from user.
 
int cli_exec_line (char *line)
 Execute command.
 
char ** cli_completion (const char *text, int start, int end)
 CLI completion function.
 
char * cli_command_generator (const char *text, int state)
 CLI command generator.
 
void * handle_cli (void *arg)
 CLI handler thread.
 

Macro Definition Documentation

◆ CLI_BUFSIZE

#define CLI_BUFSIZE   64

Definition at line 8 of file cli.h.

◆ CLI_COMMANDS_NUM

#define CLI_COMMANDS_NUM   (int) (sizeof(cli_commands) / sizeof(cli_command))

Definition at line 10 of file cli.h.

◆ CLI_DELIM

#define CLI_DELIM   " "

Definition at line 9 of file cli.h.

◆ CLI_HISTORY_FILE

#define CLI_HISTORY_FILE   "cli_history.txt"

Definition at line 11 of file cli.h.

◆ CLI_PREFIX

#define CLI_PREFIX   "BitLab> "

Definition at line 12 of file cli.h.

◆ MAX_LINE_LEN

#define MAX_LINE_LEN   256

Definition at line 7 of file cli.h.

Function Documentation

◆ cli_clear()

int cli_clear ( char **  args)

Clears CLI window.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 1098 of file cli.c.

1099{
1100 pthread_mutex_lock(&cli_mutex);
1101 if (args[0] != NULL)
1102 {
1103 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1104 "Unknown argument for clear command: %s", args[0]);
1105 print_usage("clear");
1106 pthread_mutex_unlock(&cli_mutex);
1107 return 1;
1108 }
1109 clear_cli();
1110 pthread_mutex_unlock(&cli_mutex);
1111 return 0;
1112}
void print_usage(const char *command_name)
Prints CLI command usage.
Definition cli.c:262
pthread_mutex_t cli_mutex
Definition cli.c:19
void log_message(log_level level, const char *filename, const char *source_file, const char *format,...)
Log a message used to log a message to the console or a file.
Definition log.c:89
#define BITLAB_LOG
Definition log.h:11
@ LOG_WARN
Definition log.h:31
void clear_cli()
Clear the CLI window.
Definition utils.c:33

References BITLAB_LOG, clear_cli(), cli_mutex, log_message(), LOG_WARN, and print_usage().

◆ cli_command_generator()

char * cli_command_generator ( const char *  text,
int  state 
)

CLI command generator.

Parameters
textThe text to generate.
stateThe state of the generator.
Returns
The generated command.

Definition at line 1258 of file cli.c.

1259{
1260 static int list_index, len;
1261 const char* name;
1262 if (!state)
1263 {
1264 list_index = 0;
1265 len = strlen(text);
1266 }
1267 while (list_index < CLI_COMMANDS_NUM)
1268 {
1269 name = cli_commands[list_index].cli_command_name;
1270 list_index++;
1271
1272 if (strncmp(name, text, len) == 0)
1273 return strdup(name);
1274 }
1275 return NULL;
1276}
static cli_command cli_commands[]
Definition cli.c:22
#define CLI_COMMANDS_NUM
Definition cli.h:10
program_state state
The program state used to store the state of the program.
Definition state.c:19
const char * cli_command_name
Definition cli.h:26
char * strdup(const char *str1)

References cli_command::cli_command_name, cli_commands, CLI_COMMANDS_NUM, state, and strdup().

Referenced by cli_completion().

◆ cli_completion()

char ** cli_completion ( const char *  text,
int  start,
int  end 
)

CLI completion function.

Parameters
textThe text to complete.
startThe start index.
endThe end index.
Returns
The completion.

Definition at line 1225 of file cli.c.

1226{
1227 rl_attempted_completion_over = 1;
1228 start = start; // unused
1229 end = end; // unused
1230 char* line = rl_line_buffer;
1231 int spaces = 0;
1232
1233 // print help for empty input
1234 if (strlen(line) == 0)
1235 {
1236 guarded_print("\n");
1237 print_help();
1239 return NULL;
1240 }
1241
1242 // count spaces
1243 for (long unsigned i = 0; i < strlen(line); ++i)
1244 if (line[i] == ' ')
1245 spaces++;
1246
1247 // check if the input starts with "help" and allow for one space
1248 if (((strncmp(line, "help", 4) == 0) && spaces <= 1))
1249 return rl_completion_matches(text, cli_command_generator);
1250
1251 // complete first word
1252 if (spaces == 0)
1253 return rl_completion_matches(text, cli_command_generator);
1254
1255 return NULL;
1256}
char * cli_command_generator(const char *text, int state)
CLI command generator.
Definition cli.c:1258
void print_help()
Prints CLI command help.
Definition cli.c:171
#define CLI_PREFIX
Definition cli.h:12
void guarded_print(const char *format,...)
Guarded print function.
Definition utils.c:55

References cli_command_generator(), CLI_PREFIX, guarded_print(), and print_help().

Referenced by handle_cli().

◆ cli_connect()

int cli_connect ( char **  args)

Connects to the specified IP address.

Parameters
argsThe IP address.
Returns
The exit code.

Definition at line 768 of file cli.c.

769{
770 pthread_mutex_lock(&cli_mutex);
771 if (args[0] == NULL)
772 {
774 "No arguments provided for connect command");
775 print_usage("connect");
776 pthread_mutex_unlock(&cli_mutex);
777 return 1;
778 }
779 if (args[1] != NULL)
780 {
782 "Too many arguments for connect command");
783 print_usage("connect");
784 pthread_mutex_unlock(&cli_mutex);
785 return 1;
786 }
787 char ip_address[BUFFER_SIZE];
788 if (is_numeric_address(args[0]))
789 {
790 strncpy(ip_address, args[0], BUFFER_SIZE - 1);
791 ip_address[BUFFER_SIZE - 1] = '\0';
792 guarded_print_line("Connecting to %s", ip_address);
793 connect_to_peer(ip_address);
794 }
795 else
797 "Connect command uses numeric address for peer connection. Supplied argument: %s",
798 args[0]);
799 pthread_mutex_unlock(&cli_mutex);
800 return 0;
801}
int is_numeric_address(const char *ip_addr)
Check if the IP address is a numeric address (e.g.
Definition ip.c:119
int connect_to_peer(const char *ip_addr)
Connects to a peer using the specified IP address.
#define BUFFER_SIZE
Definition utils.h:12
void guarded_print_line(const char *format,...)
Guarded print line function.
Definition utils.c:65

References BITLAB_LOG, BUFFER_SIZE, cli_mutex, connect_to_peer(), guarded_print_line(), is_numeric_address(), log_message(), LOG_WARN, and print_usage().

◆ cli_disconnect()

int cli_disconnect ( char **  args)

Disconnects from the specified node.

This function disconnects from the node specified by the given node ID. It closes the socket, terminates the thread, and logs the disconnection.

Parameters
argsThe arguments passed to the function should contain the node ID.
Returns
The exit code.

Definition at line 830 of file cli.c.

831{
832 pthread_mutex_lock(&cli_mutex);
833 if (args[0] == NULL)
834 {
836 "No arguments provided for disconnect command");
837 print_usage("disconnect");
838 pthread_mutex_unlock(&cli_mutex);
839 return 1;
840 }
841 if (args[1] != NULL)
842 {
844 "Too many arguments for disconnect command");
845 print_usage("disconnect");
846 pthread_mutex_unlock(&cli_mutex);
847 return 1;
848 }
849 int idx = atoi(args[0]);
850 guarded_print_line("Disconnecting from node %d", idx);
851 disconnect(idx);
852 pthread_mutex_unlock(&cli_mutex);
853 return 0;
854}
void disconnect(int node_id)
Disconnects from the node specified by the node ID.

References BITLAB_LOG, cli_mutex, disconnect(), guarded_print_line(), log_message(), LOG_WARN, and print_usage().

◆ cli_echo()

int cli_echo ( char **  args)

Echoes the input.

Parameters
argsInput that will be echoed.
Returns
The exit code.

Definition at line 367 of file cli.c.

368{
369 pthread_mutex_lock(&cli_mutex);
370 if (args[0] == NULL)
371 {
373 "No arguments provided for echo command");
374 print_usage("echo");
375 pthread_mutex_unlock(&cli_mutex);
376 return 1;
377 }
378 for (int i = 0; args[i] != NULL; ++i)
379 guarded_print("%s ", args[i]);
380 guarded_print("\n");
381 pthread_mutex_unlock(&cli_mutex);
382 return 0;
383}

References BITLAB_LOG, cli_mutex, guarded_print(), log_message(), LOG_WARN, and print_usage().

◆ cli_exec_line()

int cli_exec_line ( char *  line)

Execute command.

This function executes a command from line.

Parameters
lineThe string containing input from user.
Returns
The exit code.

Definition at line 1163 of file cli.c.

1164{
1165 int i = 0;
1166 int buffer_size = CLI_BUFSIZE;
1167 char** tokens = malloc(buffer_size * sizeof(char*));
1168 char* token;
1169
1170 char* command;
1171 char** args;
1172
1173 if (!tokens)
1174 {
1175 log_message(LOG_FATAL, BITLAB_LOG, __FILE__, "cli_exec_line: malloc error");
1176 exit(EXIT_FAILURE);
1177 }
1178
1179 token = strtok(line, CLI_DELIM);
1180 while (token != NULL)
1181 {
1182 tokens[i] = token;
1183 i++;
1184
1185 if (i >= buffer_size)
1186 {
1187 buffer_size += CLI_BUFSIZE;
1188 tokens = realloc(tokens, buffer_size * sizeof(char*));
1189 if (!tokens)
1190 {
1191 log_message(LOG_FATAL, BITLAB_LOG, __FILE__,
1192 "cli_exec_line: malloc error");
1193 exit(EXIT_FAILURE);
1194 }
1195 }
1196
1197 token = strtok(NULL, CLI_DELIM);
1198 }
1199 tokens[i] = NULL;
1200
1201 command = tokens[0];
1202 args = tokens + 1;
1203
1204 if (command == NULL)
1205 {
1206 free(tokens);
1207 return 1;
1208 }
1209
1210 for (i = 0; i < CLI_COMMANDS_NUM; ++i)
1211 {
1212 if (!strcmp(command, cli_commands[i].cli_command_name))
1213 {
1214 int result = (cli_commands[i].cli_command)(args);
1215 free(tokens);
1216 return result;
1217 }
1218 }
1219 guarded_print_line("Command not found! Type \"help\" to see available commands.");
1220 log_message(LOG_INFO, BITLAB_LOG, __FILE__, "Command not found: %s", command);
1221 free(tokens);
1222 return 1;
1223}
#define CLI_BUFSIZE
Definition cli.h:8
#define CLI_DELIM
Definition cli.h:9
@ LOG_INFO
Definition log.h:30
@ LOG_FATAL
Definition log.h:33
int(* cli_command)(char **args)
Definition cli.h:25
char * strtok(char *str, const char *delimiters)

References BITLAB_LOG, CLI_BUFSIZE, cli_command::cli_command, cli_commands, CLI_COMMANDS_NUM, CLI_DELIM, guarded_print_line(), LOG_FATAL, LOG_INFO, log_message(), and strtok().

Referenced by handle_cli(), and run_bitlab().

◆ cli_exit()

int cli_exit ( char **  args)

Exits BitLab CLI command.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 281 of file cli.c.

282{
283 pthread_mutex_lock(&cli_mutex);
284 if (args[0] != NULL)
285 {
286 if (strcmp(args[0], "-f") == 0 || strcmp(args[0], "--force") == 0)
287 {
288 if (args[1] != NULL)
289 {
291 "Unknown argument for exit command: \"%s\"", args[1]);
292 print_usage("exit");
293 pthread_mutex_unlock(&cli_mutex);
294 return 1;
295 }
296 log_message(LOG_WARN, BITLAB_LOG, __FILE__, "Force exiting BitLab");
297 pthread_mutex_unlock(&cli_mutex);
298 exit(0);
299 }
301 "Unknown argument for exit command: \"%s\"", args[0]);
302 print_usage("exit");
303 pthread_mutex_unlock(&cli_mutex);
304 return 1;
305 }
306 log_message(LOG_INFO, BITLAB_LOG, __FILE__, "Server shutdown requested");
307 set_exit_flag(1);
308 pthread_mutex_unlock(&cli_mutex);
309 return 0;
310}
void set_exit_flag(volatile sig_atomic_t flag)
Set the exit flag.
Definition state.c:73

References BITLAB_LOG, cli_mutex, LOG_INFO, log_message(), LOG_WARN, print_usage(), and set_exit_flag().

◆ cli_get_ip()

int cli_get_ip ( char **  args)

Gets remote IP address on an URL or host machine if no URL is provided.

Parameters
argsThe URL.
Returns
The exit code.

Definition at line 437 of file cli.c.

438{
439 pthread_mutex_lock(&cli_mutex);
440 char ip_address[BUFFER_SIZE];
441 if (args[0] == NULL)
442 {
443 get_remote_ip_address(ip_address);
444 guarded_print_line("Public IP address: %s", ip_address);
445 }
446 else
447 {
448 if (args[0] != NULL && args[1] == NULL)
449 {
450 if (is_valid_domain_address(args[0]))
451 {
452 lookup_address(args[0], ip_address);
453 guarded_print_line("IP address of %s: %s", args[0], ip_address);
454 }
455 else
456 guarded_print_line("Invalid domain address: %s", args[0]);
457 }
458 else
459 {
460 int i = 0;
461 while (args[i] != NULL)
462 {
463 ip_address[0] = '\0';
464 if (is_valid_domain_address(args[i]))
465 {
466 lookup_address(args[i], ip_address);
467 guarded_print_line("%d: IP address of %s: %s", i + 1, args[i],
468 ip_address);
469 }
470 else
471 guarded_print_line("%d: Invalid domain address: %s", i + 1,
472 args[i]);
473 i++;
474 }
475 }
476 }
477 pthread_mutex_unlock(&cli_mutex);
478 return 0;
479}
int lookup_address(const char *lookup_addr, char *ip_addr)
Perform lookup of given IP address by the domain address (e.g.
Definition ip.c:55
int is_valid_domain_address(const char *domain_addr)
Check if the IP address is a valid domain address (e.g.
Definition ip.c:136
void get_remote_ip_address(char *ip_addr)
Get the remote IP address of the machine (e.g.
Definition ip.c:33

References BUFFER_SIZE, cli_mutex, get_remote_ip_address(), guarded_print_line(), is_valid_domain_address(), and lookup_address().

◆ cli_get_line()

int cli_get_line ( char **  lineptr,
size_t *  n,
FILE *  stream 
)

Gets the line from the file stream.

Parameters
lineptrThe pointer to the line.
nThe size of the line.
streamThe file stream.
Returns
The number of characters read.

Definition at line 1114 of file cli.c.

1115{
1116 static char line[MAX_LINE_LEN];
1117 char* ptr;
1118 unsigned int len;
1119
1120 if (lineptr == NULL || n == NULL)
1121 {
1122 errno = EINVAL;
1123 return -1;
1124 }
1125
1126 if (ferror(stream))
1127 return -1;
1128
1129 if (feof(stream))
1130 return -1;
1131
1132 (void)fgets(line, MAX_LINE_LEN, stream);
1133
1134 ptr = strchr(line, '\n');
1135 if (ptr)
1136 *ptr = '\0';
1137
1138 len = strlen(line);
1139
1140 if ((len + 1) < MAX_LINE_LEN)
1141 {
1142 ptr = realloc(*lineptr, MAX_LINE_LEN);
1143 if (ptr == NULL)
1144 return (-1);
1145 *lineptr = ptr;
1146 *n = MAX_LINE_LEN;
1147 }
1148
1149 strcpy(*lineptr, line);
1150 return (len);
1151}
#define MAX_LINE_LEN
Definition cli.h:7

References MAX_LINE_LEN.

◆ cli_getaddr()

int cli_getaddr ( char **  args)

Sends a 'getaddr' message to the specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 804 of file cli.c.

805{
806 pthread_mutex_lock(&cli_mutex);
807 if (args[0] == NULL)
808 {
810 "No arguments provided for getaddr command");
811 print_usage("getaddr");
812 pthread_mutex_unlock(&cli_mutex);
813 return 1;
814 }
815 if (args[1] != NULL)
816 {
818 "Too many arguments for getaddr command");
819 print_usage("getaddr");
820 pthread_mutex_unlock(&cli_mutex);
821 return 1;
822 }
823 int idx = atoi(args[0]);
824 guarded_print_line("Sending getaddr to %d", idx);
826 pthread_mutex_unlock(&cli_mutex);
827 return 0;
828}
void send_getaddr_and_wait(int idx)
Sends a 'getaddr' message to the peer and waits for a response.

References BITLAB_LOG, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, print_usage(), and send_getaddr_and_wait().

◆ cli_getblocks()

int cli_getblocks ( char **  args)

Sends a 'getblocks' message to specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 882 of file cli.c.

883{
884 pthread_mutex_lock(&cli_mutex);
885 if (args[0] == NULL)
886 {
888 "No arguments provided for getblocks command");
889 print_usage("getblocks");
890 pthread_mutex_unlock(&cli_mutex);
891 return 1;
892 }
893 if (args[1] != NULL)
894 {
896 "Too many arguments for getblocks command");
897 print_usage("getblocks");
898 pthread_mutex_unlock(&cli_mutex);
899 return 1;
900 }
901 int idx = atoi(args[0]);
902 guarded_print_line("Sending getblocks to %d", idx);
904 pthread_mutex_unlock(&cli_mutex);
905 return 0;
906}
void send_getblocks_and_wait(int idx)
Sends a 'getblocks' message to the peer and waits for a response.

References BITLAB_LOG, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, print_usage(), and send_getblocks_and_wait().

◆ cli_getdata()

int cli_getdata ( char **  args)

Sends a 'getdata' message to specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 908 of file cli.c.

909{
910 pthread_mutex_lock(&cli_mutex);
911 if (args[0] == NULL)
912 {
914 "No arguments provided for getdata command");
915 print_usage("getdata");
916 pthread_mutex_unlock(&cli_mutex);
917 return 1;
918 }
919
920 int idx = atoi(args[0]);
921 if (idx < 0 || idx >= MAX_NODES)
922 {
924 "Invalid node index for getdata command");
925 print_usage("getdata");
926 pthread_mutex_unlock(&cli_mutex);
927 return 1;
928 }
929
930 // Count the number of hashes provided
931 size_t hash_count = 0;
932 for (int i = 1; args[i] != NULL; i++)
933 {
934 hash_count++;
935 }
936
937 if (hash_count == 0)
938 {
940 "No hashes provided for getdata command");
941 print_usage("getdata");
942 pthread_mutex_unlock(&cli_mutex);
943 return 1;
944 }
945
946 if (hash_count > 50000)
947 {
949 "Too many hashes provided for getdata command");
950 print_usage("getdata");
951 pthread_mutex_unlock(&cli_mutex);
952 return 1;
953 }
954
955 // Allocate memory for the hashes
956 unsigned char* hashes = malloc(hash_count * 32);
957 if (hashes == NULL)
958 {
960 "Failed to allocate memory for hashes");
961 pthread_mutex_unlock(&cli_mutex);
962 return 1;
963 }
964
965 // Parse the hashes from the arguments
966 for (size_t i = 0; i < hash_count; i++)
967 {
968 if (strlen(args[i + 1]) != 64)
969 {
971 "Invalid hash length for getdata command");
972 print_usage("getdata");
973 free(hashes);
974 pthread_mutex_unlock(&cli_mutex);
975 return 1;
976 }
977
978 for (size_t j = 0; j < 32; j++)
979 {
980 sscanf(&args[i + 1][j * 2], "%2hhx", &hashes[i * 32 + j]);
981 }
982 }
983
984 guarded_print_line("Sending getdata to %d with %zu hashes", idx, hash_count);
985 send_getdata_and_wait(idx, hashes, hash_count);
986
987 free(hashes);
988 pthread_mutex_unlock(&cli_mutex);
989 return 0;
990}
@ LOG_ERROR
Definition log.h:32
#define MAX_NODES
void send_getdata_and_wait(int idx, const unsigned char *hashes, size_t hash_count)
Sends a 'getdata' message to the peer and waits for a response.

References BITLAB_LOG, cli_mutex, guarded_print_line(), LOG_ERROR, log_message(), LOG_WARN, MAX_NODES, print_usage(), and send_getdata_and_wait().

◆ cli_getheaders()

int cli_getheaders ( char **  args)

Sends a 'getheaders' message to specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 856 of file cli.c.

857{
858 pthread_mutex_lock(&cli_mutex);
859 if (args[0] == NULL)
860 {
862 "No arguments provided for getheaders command");
863 print_usage("getheaders");
864 pthread_mutex_unlock(&cli_mutex);
865 return 1;
866 }
867 if (args[1] != NULL)
868 {
870 "Too many arguments for getheaders command");
871 print_usage("getheaders");
872 pthread_mutex_unlock(&cli_mutex);
873 return 1;
874 }
875 int idx = atoi(args[0]);
876 guarded_print_line("Sending getheaders to %d", idx);
878 pthread_mutex_unlock(&cli_mutex);
879 return 0;
880}
void send_getheaders_and_wait(int idx)
Sends a 'getheaders' message to the peer and waits for a response.

References BITLAB_LOG, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, print_usage(), and send_getheaders_and_wait().

◆ cli_help()

int cli_help ( char **  args)

Prints CLI command help.

Parameters
argsThe arguments passed to this function can be empty to get full program help or argument should specify one comand to get help for.
Returns
The exit code.

Definition at line 333 of file cli.c.

334{
335 pthread_mutex_lock(&cli_mutex);
336 if (args[0] != NULL)
337 {
338 if (args[1] != NULL && args[2] == NULL)
339 {
341 "Too many arguments for help command");
342 print_usage("help");
343 pthread_mutex_unlock(&cli_mutex);
344 return 1;
345 }
346 for (long unsigned i = 0; i < sizeof(cli_commands) / sizeof(cli_command); ++i)
347 {
348 if (strcmp(args[0], cli_commands[i].cli_command_name) == 0)
349 {
350 if (cli_commands[i].cli_command_detailed_desc)
351 guarded_print_line(cli_commands[i].cli_command_detailed_desc);
352 else
353 guarded_print_line(" * %s - Detailed information not included.",
354 args[0]);
355 pthread_mutex_unlock(&cli_mutex);
356 return 0;
357 }
358 }
359 guarded_print_line(" * %s - Unknown command.", args[0]);
360 }
361 else
362 print_help();
363 pthread_mutex_unlock(&cli_mutex);
364 return 0;
365}
CLI command structure.
Definition cli.h:24

References BITLAB_LOG, cli_commands, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, print_help(), and print_usage().

◆ cli_history()

int cli_history ( char **  args)

Prints CLI command history.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 312 of file cli.c.

313{
314 pthread_mutex_lock(&cli_mutex);
315 if (args[0] != NULL)
316 {
318 "Unknown argument for history command: \"%s\"", args[0]);
319 print_usage("history");
320 pthread_mutex_unlock(&cli_mutex);
321 return 1;
322 }
323 HIST_ENTRY** history_entries = history_list();
324 if (history_entries)
325 {
326 for (int i = 0; history_entries[i] != NULL; ++i)
327 guarded_print_line("%d: %s", i + 1, history_entries[i]->line);
328 }
329 pthread_mutex_unlock(&cli_mutex);
330 return 0;
331}

References BITLAB_LOG, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, and print_usage().

◆ cli_info()

int cli_info ( char **  args)

Prints program information.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 481 of file cli.c.

482{
483 pthread_mutex_lock(&cli_mutex);
484 if (args[0] != NULL)
485 {
487 "Unknown argument for info command: %s", args[0]);
488 print_usage("info");
489 pthread_mutex_unlock(&cli_mutex);
490 return 1;
491 }
492
493 guarded_print_line("BitLab v%s", BITLAB_VERSION);
494 guarded_print_line("Built on %s %s", __DATE__, __TIME__);
497 {
498 guarded_print_line("Peer discovery: active");
499
501 guarded_print_line("Peer discovery in progress: true");
502 else
503 guarded_print_line("Peer discovery in progress: false");
505 guarded_print_line("Peer discovery succeeded: true");
506 else
507 guarded_print_line("Peer discovery succeeded: false");
509 guarded_print_line("Peer discovery daemon: true");
510 else
511 guarded_print_line("Peer discovery daemon: false");
513 guarded_print_line("Peer discovery hardcoded seeds: true");
514 else
515 guarded_print_line("Peer discovery hardcoded seeds: false");
517 guarded_print_line("Peer discovery DNS lookup: true");
518 else
519 guarded_print_line("Peer discovery DNS lookup: false");
520 }
521 else
522 guarded_print_line("Peer discovery: inactive");
523
524 pthread_mutex_unlock(&cli_mutex);
525 return 0;
526}
void print_program_state()
Print the program state.
Definition state.c:63
#define BITLAB_VERSION
Definition state.h:4
program_operation operation
The program operation used to store all current operations of the program.
Definition state.c:40
bool peer_discovery_succeeded
Definition state.h:51
bool peer_discovery_in_progress
Definition state.h:50
bool peer_discovery_daemon
Definition state.h:52
bool peer_discovery_dns_lookup
Definition state.h:54
bool peer_discovery_hardcoded_seeds
Definition state.h:53
bool peer_discovery
Definition state.h:49

References BITLAB_LOG, BITLAB_VERSION, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, operation, program_operation::peer_discovery, program_operation::peer_discovery_daemon, program_operation::peer_discovery_dns_lookup, program_operation::peer_discovery_hardcoded_seeds, program_operation::peer_discovery_in_progress, program_operation::peer_discovery_succeeded, print_program_state(), and print_usage().

◆ cli_inv()

int cli_inv ( char **  args)

Sends a 'inv' message to specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 992 of file cli.c.

993{
994 pthread_mutex_lock(&cli_mutex);
995 if (args[0] == NULL)
996 {
998 "Insufficient arguments provided for inv command");
999 print_usage("inv");
1000 pthread_mutex_unlock(&cli_mutex);
1001 return 1;
1002 }
1003 if (args[1] != NULL)
1004 {
1005 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1006 "Too many arguments for inv command");
1007 print_usage("inv");
1008 pthread_mutex_unlock(&cli_mutex);
1009 return 1;
1010 }
1011
1012 int idx = atoi(args[0]);
1013
1014 // Load inventory data from blocks.dat
1015 size_t inv_len;
1016 unsigned char* inv_data = load_blocks_from_file("blocks.dat", &inv_len);
1017 if (!inv_data)
1018 {
1019 log_message(LOG_ERROR, BITLAB_LOG, __FILE__,
1020 "Failed to load inventory data from blocks.dat");
1021 pthread_mutex_unlock(&cli_mutex);
1022 return 1;
1023 }
1024
1025 size_t inv_count = inv_len / 36;
1026 printf("inv_len: %zu, inv_count: %zu\n", inv_len, inv_count);
1027
1028 // Send the 'inv' message
1029 send_inv_and_wait(idx, inv_data, inv_count);
1030
1031 free(inv_data);
1032 pthread_mutex_unlock(&cli_mutex);
1033 return 0;
1034}
void send_inv_and_wait(int idx, const unsigned char *inv_data, size_t inv_count)
Sends an 'inv' message to the peer and waits for a response.
unsigned char * load_blocks_from_file(const char *filename, size_t *payload_len)

References BITLAB_LOG, cli_mutex, load_blocks_from_file(), LOG_ERROR, log_message(), LOG_WARN, print_usage(), and send_inv_and_wait().

◆ cli_list()

int cli_list ( char **  args)

Lists all connected nodes.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 1082 of file cli.c.

1083{
1084 pthread_mutex_lock(&cli_mutex);
1085 if (args[0] != NULL)
1086 {
1087 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1088 "Too many arguments for getaddr command");
1089 print_usage("getaddr");
1090 pthread_mutex_unlock(&cli_mutex);
1091 return 1;
1092 }
1094 pthread_mutex_unlock(&cli_mutex);
1095 return 0;
1096}
void list_connected_nodes()
Lists all connected nodes and their details.

References BITLAB_LOG, cli_mutex, list_connected_nodes(), log_message(), LOG_WARN, and print_usage().

◆ cli_peer_discovery()

int cli_peer_discovery ( char **  args)

Discovers Bitcoin peers.

Parameters
argsThe arguments passed to the function should match those specified in 'help peerdiscovery'.
Returns
The exit code.

Definition at line 528 of file cli.c.

529{
530 pthread_mutex_lock(&cli_mutex);
531
532 // defaults
533 bool daemon = PEER_DISCOVERY_DEFAULT_DAEMON;
534 bool hardcoded_seeds = PEER_DISCOVERY_DEFAULT_HARDCODED_SEEDS;
535 bool dns_lookup = PEER_DISCOVERY_DEFAULT_DNS_LOOKUP;
536
537 bool daemon_set = false;
538 bool hardcoded_seeds_set = false;
539 bool dns_lookup_set = false;
540
541 // before checking program state, ensure command is only used with valid arguments to avoid confusion
542 if (args[0] != NULL)
543 {
544 for (int i = 0; args[i] != NULL; ++i)
545 {
546 if (strcmp(args[i], "-d") == 0 || strcmp(args[i], "--daemon") == 0)
547 {
548 if (daemon_set)
549 {
551 "Daemon flag already set for peerdiscovery command");
552 print_usage("peerdiscovery");
553 pthread_mutex_unlock(&cli_mutex);
554 return 1;
555 }
556 daemon = true;
557 daemon_set = true;
558 }
559 else if (strcmp(args[i], "-h") == 0 || strcmp(args[i], "--hardcoded") == 0)
560 {
561 if (hardcoded_seeds_set || dns_lookup_set)
562 {
564 "Hardcoded seeds or DNS lookup flag already set for peerdiscovery command");
565 print_usage("peerdiscovery");
566 pthread_mutex_unlock(&cli_mutex);
567 return 1;
568 }
569 hardcoded_seeds = true;
570 dns_lookup = false;
571
572 hardcoded_seeds_set = true;
573 }
574 else if (strcmp(args[i], "-l") == 0 || strcmp(args[i], "--dns-lookup") == 0)
575 {
576 if (dns_lookup_set || hardcoded_seeds_set)
577 {
579 "DNS lookup or hardcoded seeds flag already set for peerdiscovery command");
580 print_usage("peerdiscovery");
581 pthread_mutex_unlock(&cli_mutex);
582 return 1;
583 }
584
585 if (args[i + 1] == NULL)
587 "Missing domain argument for DNS lookup flag for peerdiscovery command, default will be used");
588 if (args[i + 2] != NULL)
589 {
591 "Too many arguments for DNS lookup flag for peerdiscovery command");
592 print_usage("peerdiscovery");
593 pthread_mutex_unlock(&cli_mutex);
594 return 1;
595 }
596
597 dns_lookup = true;
598 hardcoded_seeds = false;
599
600 dns_lookup_set = true;
601 }
602 else
603 {
604 if (dns_lookup_set)
605 {
608 "Set DNS domain for peerdiscovery command: %s",
609 args[i]);
610 else
611 {
613 "Failed to set DNS domain for peerdiscovery command");
614 pthread_mutex_unlock(&cli_mutex);
615 return 1;
616 }
617 }
618 else
619 {
621 "Unknown argument for peerdiscovery command: %s",
622 args[i]);
623 print_usage("peerdiscovery");
624 pthread_mutex_unlock(&cli_mutex);
625 return 1;
626 }
627 }
628 }
629 }
630
631 // process current state and provided arguments if state allows
633 {
634 if (daemon)
635 {
637 "Peer discovery already in progress");
639 "Peer discovery already in progress. Use \"peerdiscovery\" to check results later or \"info\" to see the status. Any additional arguments will be ignored until the results are cleared.");
640 pthread_mutex_unlock(&cli_mutex);
641 return 1;
642 }
643 else // wait for peer discovery to finish
644 {
646 "Connected to peer discovery daemon. Arguments ignored if provided. Waiting for results...");
648 usleep(100000); // 100 ms
649 usleep(1000000); // 1s
650 }
651 }
652 else
653 {
654 // check if previous peer discovery attempt failed
655 bool results_successful = get_peer_discovery_succeeded();
656 if (get_peer_discovery() && !results_successful)
658 "Peer discovery previous attempt failed. Allowing new attempt...");
659
660 if (!results_successful) // results does not exist or failed and are not cleared
661 {
662 // [ ] Add clearing results
663 // set states
664 set_peer_discovery(true);
666 set_peer_discovery_hardcoded_seeds(hardcoded_seeds);
668
669 if (daemon)
670 {
672 "Peer discovery in background");
674 "Peer discovery started as daemon. Use \"peerdiscovery\" to check results or \"info\" to see the status.");
675 pthread_mutex_unlock(&cli_mutex);
676 return 0;
677 }
678 else // wait for peer discovery to finish
679 {
680 guarded_print_line("Peer discovery started. Waiting for results...");
682 usleep(100000); // 100 ms
683 usleep(1000000); // 1s
684 }
685 }
686 }
687
689
690 pthread_mutex_unlock(&cli_mutex);
691 return 0;
692}
void print_peer_queue()
Print the peer queue.
Definition peer_queue.c:103
bool set_peer_discovery_daemon(bool value)
Set the peer discovery daemon state.
Definition state.c:174
bool get_peer_discovery()
Get the peer discovery operation.
Definition state.c:150
bool set_peer_discovery_hardcoded_seeds(bool value)
Set the peer discovery hardcoded seeds state.
Definition state.c:182
bool get_peer_discovery_in_progress()
Get the peer discovery in progress state.
Definition state.c:158
bool set_peer_discovery_dns_lookup(bool value)
Set the peer discovery DNS lookup state.
Definition state.c:190
bool set_peer_discovery_dns_domain(const char *domain)
Set the peer discovery DNS domain.
Definition state.c:222
bool get_peer_discovery_succeeded()
Get the peer discovery succeeded state.
Definition state.c:166
#define PEER_DISCOVERY_DEFAULT_DNS_LOOKUP
Definition state.h:8
bool set_peer_discovery(bool value)
Set the peer discovery operation.
Definition state.c:125
#define PEER_DISCOVERY_DEFAULT_DAEMON
Definition state.h:6
#define PEER_DISCOVERY_DEFAULT_HARDCODED_SEEDS
Definition state.h:7
void usleep(unsigned int usec)

References BITLAB_LOG, cli_mutex, get_peer_discovery(), get_peer_discovery_in_progress(), get_peer_discovery_succeeded(), guarded_print_line(), LOG_INFO, log_message(), LOG_WARN, PEER_DISCOVERY_DEFAULT_DAEMON, PEER_DISCOVERY_DEFAULT_DNS_LOOKUP, PEER_DISCOVERY_DEFAULT_HARDCODED_SEEDS, print_peer_queue(), print_usage(), set_peer_discovery(), set_peer_discovery_daemon(), set_peer_discovery_dns_domain(), set_peer_discovery_dns_lookup(), set_peer_discovery_hardcoded_seeds(), and usleep().

◆ cli_ping()

int cli_ping ( char **  args)

Pings the specified IP address.

Parameters
argsThe IP address.
Returns
The exit code.

Definition at line 694 of file cli.c.

695{
696 pthread_mutex_lock(&cli_mutex);
697 int count = 4;
698 int sleep_time = 1;
699 char ip_address[BUFFER_SIZE] = { 0 };
700
701 int i = 0;
702 while (args[i] != NULL)
703 {
704 if (strcmp(args[i], "-c") == 0 || strcmp(args[i], "--count") == 0)
705 {
706 if (args[i + 1] == NULL)
707 {
709 "Missing count value for ping command.");
710 print_usage("ping");
711 pthread_mutex_unlock(&cli_mutex);
712 return 1;
713 }
714
715 count = strtol(args[i + 1], NULL, 10);
716 if (count <= 0)
717 {
718 log_message(LOG_WARN, BITLAB_LOG, __FILE__, "Invalid count value: %s",
719 args[i + 1]);
720 print_usage("ping");
721 pthread_mutex_unlock(&cli_mutex);
722 return 1;
723 }
724 i += 2;
725 }
726 else if (ip_address[0] == '\0')
727 {
728 if (strlen(args[i]) >= BUFFER_SIZE)
729 {
731 "Invalid IP address for ping command.");
732 print_usage("ping");
733 pthread_mutex_unlock(&cli_mutex);
734 return 1;
735 }
736 strncpy(ip_address, args[i], BUFFER_SIZE - 1);
737 i++;
738 }
739 else
740 {
742 "Too many arguments for ping command: %s", args[i]);
743 print_usage("ping");
744 pthread_mutex_unlock(&cli_mutex);
745 return 1;
746 }
747 }
748
749 if (ip_address[0] == '\0')
750 {
752 "Missing IP address for ping command.");
753 print_usage("ping");
754 pthread_mutex_unlock(&cli_mutex);
755 return 1;
756 }
757
758 guarded_print_line("Pinging %s with count %d", ip_address, count);
759 char command[BUFFER_SIZE];
760 snprintf(command, sizeof(command), "ping -c %d -i %d %s", count, sleep_time,
761 ip_address);
762 system(command);
763
764 pthread_mutex_unlock(&cli_mutex);
765 return 0;
766}

References BITLAB_LOG, BUFFER_SIZE, cli_mutex, guarded_print_line(), log_message(), LOG_WARN, and print_usage().

◆ cli_read_line()

char * cli_read_line ( void  )

Reads input from user.

WARNING: char* returned from this function must be freed.

Returns
The string containing input from user.

Definition at line 1153 of file cli.c.

1154{
1155 pthread_mutex_lock(&cli_mutex);
1156 char* line = readline(CLI_PREFIX);
1157 if (line && *line)
1158 add_history(line);
1159 pthread_mutex_unlock(&cli_mutex);
1160 return line;
1161}

References cli_mutex, and CLI_PREFIX.

Referenced by handle_cli().

◆ cli_tx()

int cli_tx ( char **  args)

Sends a 'tx' message to specified peer.

Parameters
argsThe index of the peer.
Returns
The exit code.

Definition at line 1036 of file cli.c.

1037{
1038 pthread_mutex_lock(&cli_mutex);
1039 if (args[0] == NULL || args[1] == NULL)
1040 {
1041 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1042 "No arguments provided for tx command");
1043 print_usage("tx");
1044 pthread_mutex_unlock(&cli_mutex);
1045 return 1;
1046 }
1047
1048 int idx = atoi(args[0]);
1049 if (idx < 0 || idx >= MAX_NODES)
1050 {
1051 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1052 "Invalid node index for tx command");
1053 print_usage("tx");
1054 pthread_mutex_unlock(&cli_mutex);
1055 return 1;
1056 }
1057
1058 // Parse the transaction data from the arguments
1059 size_t tx_size = strlen(args[1]) / 2;
1060 unsigned char* tx_data = malloc(tx_size);
1061 if (tx_data == NULL)
1062 {
1063 log_message(LOG_ERROR, BITLAB_LOG, __FILE__,
1064 "Failed to allocate memory for transaction data");
1065 pthread_mutex_unlock(&cli_mutex);
1066 return 1;
1067 }
1068
1069 for (size_t i = 0; i < tx_size; i++)
1070 {
1071 sscanf(&args[1][i * 2], "%2hhx", &tx_data[i]);
1072 }
1073
1074 guarded_print_line("Sending transaction to %d with size %zu", idx, tx_size);
1075 send_tx(idx, tx_data, tx_size);
1076
1077 free(tx_data);
1078 pthread_mutex_unlock(&cli_mutex);
1079 return 0;
1080}
void send_tx(int idx, const unsigned char *tx_data, size_t tx_size)
Sends a 'tx' message to the specified node.

References BITLAB_LOG, cli_mutex, guarded_print_line(), LOG_ERROR, log_message(), LOG_WARN, MAX_NODES, print_usage(), and send_tx().

◆ cli_whoami()

int cli_whoami ( char **  args)

Prints the user name.

Parameters
argsThe arguments passed to the function should be empty.
Returns
The exit code.

Definition at line 385 of file cli.c.

386{
387 pthread_mutex_lock(&cli_mutex);
388 bool full_information = false;
389 if (args[0] != NULL)
390 {
391 if (strcmp(args[0], "-f") == 0 || strcmp(args[0], "--full") == 0)
392 {
393 if (args[1] != NULL)
394 {
396 "Unknown argument for whoami command: \"%s\"", args[1]);
397 print_usage("whoami");
398 pthread_mutex_unlock(&cli_mutex);
399 return 1;
400 }
401 full_information = true;
402 }
403 else
404 {
406 "Unknown argument for whoami command: \"%s\"", args[0]);
407 print_usage("whoami");
408 pthread_mutex_unlock(&cli_mutex);
409 return 1;
410 }
411 }
412
413 if (!full_information)
414 guarded_print_line("%s", getenv("USER"));
415 else
416 {
417 char ip_address[BUFFER_SIZE];
418 get_local_ip_address(ip_address);
419
420 if (getenv("USER") == NULL)
421 guarded_print_line("Unknown user");
422 else if (strcmp(getenv("USER"), "root") == 0)
423 guarded_print_line("You are \033[1;31m%s\033[0m", getenv("USER"));
424 else
425 guarded_print_line("You are \033[1;34m%s\033[0m", getenv("USER"));
426
427 guarded_print_line("Local IP address: %s", ip_address);
428
429 get_remote_ip_address(ip_address);
430 guarded_print_line("Public IP address: %s", ip_address);
431 }
432
433 pthread_mutex_unlock(&cli_mutex);
434 return 0;
435}
void get_local_ip_address(char *ip_addr)
Get the local IP address of the machine (e.g.
Definition ip.c:11

References BITLAB_LOG, BUFFER_SIZE, cli_mutex, get_local_ip_address(), get_remote_ip_address(), guarded_print_line(), log_message(), LOG_WARN, and print_usage().

◆ create_history_dir()

const char * create_history_dir ( )

Create history directory.

Returns
The history directory.

Definition at line 1328 of file cli.c.

1329{
1330 const char* home = getenv("HOME");
1331 if (home == NULL)
1332 return NULL;
1333 const char* suffix = "/.bitlab/history";
1334 char* logs_dir = malloc(strlen(home) + strlen(suffix) + 1);
1335 if (logs_dir == NULL)
1336 return NULL;
1337 strcpy(logs_dir, home);
1338 strcat(logs_dir, suffix);
1339 return logs_dir;
1340}
static const char * logs_dir
Definition log.c:18

References logs_dir.

Referenced by handle_cli().

◆ handle_cli()

void * handle_cli ( void *  arg)

CLI handler thread.

Parameters
argNot used. Write dummy code for no warning.

Definition at line 1278 of file cli.c.

1279{
1280 char* line = NULL;
1282 struct stat st = { 0 };
1283
1284 if (stat(cli_history_dir, &st) == -1 && mkdir(cli_history_dir, 0700) != 0)
1285 log_message(LOG_WARN, BITLAB_LOG, __FILE__,
1286 "Failed to create history directory");
1287
1288 char full_path[BUFFER_SIZE];
1289 snprintf(full_path, sizeof(full_path), "%s/%s", cli_history_dir, CLI_HISTORY_FILE);
1290 read_history(full_path);
1291 usleep(50000); // 50 ms
1292
1293 rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
1294 rl_completer_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
1295 rl_completer_quote_characters = "\"\\'`";
1296 rl_completion_append_character = '\0';
1297 rl_attempted_completion_over = 1;
1298 rl_attempted_completion_function = cli_completion;
1299 rl_getc_function = getc;
1300 rl_catch_signals = 0;
1301
1302 while (!get_exit_flag())
1303 {
1304 line = cli_read_line();
1305 if (line && *line)
1306 {
1307 cli_exec_line(line);
1308 write_history(full_path);
1309 }
1310 if (line)
1311 {
1312 free(line);
1313 line = NULL;
1314 }
1315 }
1316 if (arg)
1317 {
1318 } // dummy code to avoid unused parameter warning
1319 if (cli_history_dir != NULL)
1320 {
1321 free((void*)cli_history_dir);
1322 cli_history_dir = NULL;
1323 }
1324 log_message(LOG_INFO, BITLAB_LOG, __FILE__, "Exiting CLI thread");
1325 pthread_exit(NULL);
1326}
const char * create_history_dir()
Create history directory.
Definition cli.c:1328
char ** cli_completion(const char *text, int start, int end)
CLI completion function.
Definition cli.c:1225
static const char * cli_history_dir
Definition cli.c:16
char * cli_read_line(void)
Reads input from user.
Definition cli.c:1153
int cli_exec_line(char *line)
Execute command.
Definition cli.c:1163
#define CLI_HISTORY_FILE
Definition cli.h:11
sig_atomic_t get_exit_flag()
Get the exit flag.
Definition state.c:80

References BITLAB_LOG, BUFFER_SIZE, cli_completion(), cli_exec_line(), cli_history_dir, CLI_HISTORY_FILE, cli_read_line(), create_history_dir(), get_exit_flag(), LOG_INFO, log_message(), LOG_WARN, and usleep().

Referenced by run_bitlab().

◆ print_commands()

void print_commands ( )

Prints CLI commands.

Definition at line 275 of file cli.c.

276{
277 for (int i = 0; i < CLI_COMMANDS_NUM; ++i)
278 guarded_print_line("%s", cli_commands[i].cli_command_name);
279}

References cli_commands, CLI_COMMANDS_NUM, and guarded_print_line().

◆ print_help()

void print_help ( )

Prints CLI command help.

Definition at line 171 of file cli.c.

172{
173 int longest_command_length = 0;
174 int longest_parameters_length = 0;
175 for (int i = 0; i < CLI_COMMANDS_NUM; ++i)
176 {
177 int cmd_length = 0;
178 int param_length = 0;
179
180 char* space_pos = strchr(cli_commands[i].cli_command_usage, ' ');
181 if (space_pos)
182 {
183 cmd_length = space_pos - cli_commands[i].cli_command_usage;
184 // only command length
185 param_length = strlen(space_pos + 1); // parameters length
186 }
187 else
188 {
189 cmd_length = strlen(cli_commands[i].cli_command_usage);
190 }
191
192 if (cmd_length > longest_command_length)
193 longest_command_length = cmd_length;
194 if (param_length > longest_parameters_length)
195 longest_parameters_length = param_length;
196 }
197
198 int longest_description_length = 0;
199 for (int i = 0; i < CLI_COMMANDS_NUM; ++i)
200 {
201 int length = strlen(cli_commands[i].cli_command_brief_desc);
202 if (length > longest_description_length)
203 longest_description_length = length;
204 }
205
206 char* dashes_command = (char*)malloc(longest_command_length + 1);
207 memset(dashes_command, '-', longest_command_length);
208 dashes_command[longest_command_length] = '\0';
209
210 char* dashes_params = (char*)malloc(longest_parameters_length + 1);
211 memset(dashes_params, '-', longest_parameters_length);
212 dashes_params[longest_parameters_length] = '\0';
213
214 char* dashes_description = (char*)malloc(longest_description_length + 1);
215 memset(dashes_description, '-', longest_description_length);
216 dashes_description[longest_description_length] = '\0';
217
218 guarded_print_line("\033[1m%-*s | %-*s | %s\033[0m",
219 longest_command_length, "Command",
220 longest_parameters_length, "Parameters",
221 "Description");
222 guarded_print_line("%s-+-%s-+-%s",
223 dashes_command, dashes_params, dashes_description);
224
225 for (int i = 0; i < CLI_COMMANDS_NUM; ++i)
226 {
227 const char* usage = cli_commands[i].cli_command_usage;
228 const char* description = cli_commands[i].cli_command_brief_desc;
229
230 // split the command and its parameters
231 char command[longest_command_length + 1];
232 char parameters[longest_parameters_length + 1];
233 char* params = strchr(usage, ' ');
234
235 if (params)
236 {
237 int cmd_length = params - usage;
238 strncpy(command, usage, cmd_length);
239 command[cmd_length] = '\0';
240 strncpy(parameters, params + 1, longest_parameters_length);
241 parameters[longest_parameters_length] = '\0';
242 }
243 else
244 {
245 strncpy(command, usage, longest_command_length);
246 command[longest_command_length] = '\0';
247 parameters[0] = '\0';
248 }
249
250 // print the row
251 guarded_print_line("%-*s | %-*s | %s",
252 longest_command_length, command,
253 longest_parameters_length, parameters,
254 description);
255 }
256
257 free(dashes_command);
258 free(dashes_params);
259 free(dashes_description);
260}
const char * cli_command_brief_desc
Definition cli.h:27
const char * cli_command_usage
Definition cli.h:29

References cli_command::cli_command_brief_desc, cli_command::cli_command_usage, cli_commands, CLI_COMMANDS_NUM, and guarded_print_line().

Referenced by cli_completion(), and cli_help().

◆ print_usage()

void print_usage ( const char *  command_name)

Prints CLI command usage.

Parameters
command_nameThe name of the command.

Definition at line 262 of file cli.c.

263{
264 for (int i = 0; i < CLI_COMMANDS_NUM; ++i)
265 {
266 if (strcmp(command_name, cli_commands[i].cli_command_name) == 0)
267 {
268 guarded_print_line("Usage: %s", cli_commands[i].cli_command_usage);
269 return;
270 }
271 }
272 guarded_print_line("Unknown command: %s", command_name);
273}

References cli_commands, CLI_COMMANDS_NUM, and guarded_print_line().

Referenced by cli_clear(), cli_connect(), cli_disconnect(), cli_echo(), cli_exit(), cli_getaddr(), cli_getblocks(), cli_getdata(), cli_getheaders(), cli_help(), cli_history(), cli_info(), cli_inv(), cli_list(), cli_peer_discovery(), cli_ping(), cli_tx(), and cli_whoami().