c-template
command_line.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <argtable3.h>
6 #include "../../include/utils/colors.h"
7 #include "../../include/utils/command_line.h"
8 #include "../../include/utils/array_len.h"
9 #include "../../include/utils/logger.h"
10 #include "../../include/utils/safe_mem.h"
11 
12 /*! @brief intializes a new command_object to have commands loaded into
13 */
14 command_object *new_command_object(int argc, char *argv[]) {
15  // if too many arguments have been provided return a null pointer
16  if (argc > MAX_COMMAND_ARGS) {
17  print_colored(COLORS_RED, "too many command line arguments provided\n");
18  return NULL;
19  }
20  // allocate memory equal to the size of command_object combined with the size of all provided arguments
21  // and typecast it to command_object *
22  // command_object *pcobj = (command_object *)malloc(sizeof(command_object) + sizeof(*argv));
23  // this prevents valgrind from reporting an error
24  command_object *pcobj = calloc(sizeof(command_object), sizeof(*argv));
25  if (pcobj == NULL) {
26  printf("failed to malloc command_object\n");
27  return NULL;
28  }
29  // set arg count
30  pcobj->argc = argc;
31  // set command_count
32  pcobj->command_count = 0;
33  // parse cli arguments provided by user and assign to pcobj
34  for (int i = 0; i < argc; i++) {
35  pcobj->argv[i] = malloc(strlen(argv[i]) + 1);
36  if (pcobj->argv[i] == NULL) {
37  printf("failed to malloc argv space\n");
38  return NULL;
39  }
40  strcpy(pcobj->argv[i], argv[i]);
41  }
42  return pcobj;
43 }
44 
45 /*! @brief loads command handler and makes it executable
46 */
48  if (self->command_count >= MAX_COMMANDS) {
49  print_colored(COLORS_RED, "maximum number of commands\n");
50  return -1;
51  }
52  int n = self->command_count++;
53  self->commands[n] = command;
54  return 0;
55 }
56 
57 /*! @brief checks to see if we have a command named according to run and executes it
58 */
59 int execute(command_object *self, char *run) {
60  for (int i = 0; i < self->command_count; i++) {
61  if (strcmp(self->commands[i]->name, run) == 0) {
62  self->commands[i]->callback(self->argc, self->argv);
63  print_colored(COLORS_GREEN, "[info] command executed successfully\n");
64  return 0;
65  }
66  }
67  print_colored(COLORS_RED, "[error] failed to execute command\n");
68  return -1;
69 }
70 
71 /*! @brief frees memory allocated for the command_object and sets pointer to null
72  * for some reason this is causing an address boundary error
73 */
75  for (int i = 0; i < self->command_count; i++) {
76  free(self->commands[i]);
77  }
78  free(self);
79 }
80 
81 // validates argtable and parses command line arguments
82 int parse_args(int argc, char *argv[], void *argtable[]) {
83  if (arg_nullcheck(argtable) != 0) {
84  return -1;
85  }
86  int nerrors = arg_parse(argc, argv, argtable);
87  // handle help before errors
88  if (help->count > 0) {
89  print_help(argv[0], argtable);
90  return -2;
91  }
92  if (nerrors > 0) {
93  arg_print_errors(stdout, end, "main");
94  return -1;
95  }
96  return 0;
97 }
98 
99 void print_help(char *program_name, void *argtable[]) {
100  printf("Usage: %s", program_name);
101  arg_print_syntax(stdout, argtable, "\n");
102  arg_print_glossary(stdout, argtable, " %-25s %s\n");
103 }
104 
105 // sets up default arguments, you will have to do this for user defined args
106 void setup_args(const char *version_string) {
107  help = arg_litn(NULL, "help", 0, 1, "displays help menu");
108  version = arg_litn(NULL, "version", 0, 1, version_string);
109  file = arg_filen(NULL, "file", "<file>", 0, 10, "file(s) to load data from max of 10");
110  output = arg_filen(NULL, "output", "<file>", 0, 1, "file to output data too");
111  command_to_run = arg_strn("c", "command", "<command>", 0, 1, "command to run");
112  end = arg_end(20);
113 }
114 
116  char *run_command = malloc(strlen(*command_to_run->sval));
117  if (run_command == NULL) {
118  printf("failed to malloc run_command\n");
119  return NULL;
120  }
121  strcpy(run_command, (char *)*command_to_run->sval);
122  return run_command;
123 }
command_to_run
struct arg_str * command_to_run
Definition: command_line.h:27
print_help
void print_help(char *program_name, void *argtable[])
formats output
Definition: command_line.c:99
parse_args
int parse_args(int argc, char *argv[], void *argtable[])
parses arguments, and checks for any errors
Definition: command_line.c:82
COLORS_RED
@ COLORS_RED
Definition: colors.h:26
free_command_object
void free_command_object(command_object *self)
frees memory allocated for the command_object and sets pointer to null for some reason this is causin...
Definition: command_line.c:74
load_command
int load_command(command_object *self, command_handler *command)
loads command handler and makes it executable
Definition: command_line.c:47
MAX_COMMANDS
#define MAX_COMMANDS
Definition: command_line.h:18
help
struct arg_lit * help
Definition: command_line.h:26
setup_args
void setup_args(const char *version_string)
setups the default argtable arguments
Definition: command_line.c:106
COLORS_GREEN
@ COLORS_GREEN
Definition: colors.h:26
command_handler
Definition: command_line.h:40
MAX_COMMAND_ARGS
#define MAX_COMMAND_ARGS
Definition: command_line.h:22
execute
int execute(command_object *self, char *run)
checks to see if we have a command named according to run and executes it
Definition: command_line.c:59
command::argc
int argc
Definition: command_line.h:50
command
Definition: command_line.h:48
file
struct arg_file * file
Definition: command_line.h:28
command::argv
char * argv[32]
Definition: command_line.h:51
end
struct arg_end * end
Definition: command_line.h:29
get_run_command
char * get_run_command()
returns the value of command_to_run
Definition: command_line.c:115
new_command_object
command_object * new_command_object(int argc, char *argv[])
intializes a new command_object to have commands loaded into
Definition: command_line.c:14
command::command_count
int command_count
Definition: command_line.h:49
output
struct arg_file * output
Definition: command_line.h:28
version
struct arg_lit * version
Definition: command_line.h:26
print_colored
void print_colored(COLORS color, char *message)
prints message to stdout with the given color
Definition: colors.c:43