Skip to content
Snippets Groups Projects
cli.c 3.46 KiB
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <libgen.h>
#include <getopt.h>

#include "cli.h"

int main(int argc, char **argv)
{
	int cmdID = -1;
	char * command;
	int c;
	int i , useSymlink = 0;
	struct backend_conn  *conn;
	int needCliHelp = 0, needCommandHelp = 0;

	// Determine if the cli was called using a symlink
	command = basename(argv[0]);
	for(i = 0; i < MAX_COMMANDS; ++i) {
		if (strncmp(command, commandNames[i], strlen(commandNames[i])) == 0)
		{
			cmdID = i;
			useSymlink = 1;
		}
	}

	// Verify the user has entered enough information to continue
	if (argc < 2 && !useSymlink) {
		printf("Incorrect usage :\n");
		printf("Usage Syntax: \n\t./Cli command [options...]\n\n");
		printf("For a list of available 'command' names\n\t./Cli --help\n\n");
		printf("For a list of available options for a 'command'\n\t./Cli command --help\n");
		return -1;
	}

	if (!useSymlink) {
		// Determine if the user called for help on the cli
		needCliHelp = (strncmp("--help", argv[1], strlen(argv[1])) ==  0);
	}

	// If the user runs './Cli help' , provide the user with a list of commands available.
	if (needCliHelp) {
		printf("Usage Syntax: \n\t./Cli command [options...]\n\n");
		printf("Available 'command' names include the following\n");
		for(int i = 0; i < MAX_COMMANDS; ++i) {
			printf("\t '%s'\n",commandNames[i]);
		}
		return 0;
	}

	// recognize which cli command the user has entered
	if (cmdID == -1) {
		command = argv[1];
		for(i = 0; i < MAX_COMMANDS; ++i) {
			if (strncmp(command, commandNames[i], strlen(commandNames[i])) == 0)
			{
				cmdID = i;
			}	
		}
	}

	if (cmdID == -1){
		printf("Could not match '%s' with a command. Please try again...\n", command);
		printf("For help running the program, run ./Cli --help\n");
		return -1;
	}

	// Determine if the user called for help on the command
	if (!useSymlink && argc > 2) {
		if (strncmp("--help", argv[2], strlen(argv[2])) == 0) {
			needCommandHelp = 1;
		}
	} else if (useSymlink && argc > 1) {
		if (strncmp("--help", argv[1], strlen(argv[1])) == 0) {
			needCommandHelp = 1;
		}
	}
	
	/**
	 * If the user has asked for help, and we have already found
	 *  the command that they are trying to use. Then we need
	 *  to be able to provide the help info wihtout the 
	 *  requirement of the backend
	 *
	 * It is important to note that this will only work if the 
	 * 	command the user has asked for handles this help case 
	 * 
	 */

	// Only require the backend if we will need to use it.
	if (!needCommandHelp) {
		// Create the connection to the backend
		conn = ucart_backendConnect();
		if (conn == NULL) {
			return -1;
		}
	}

	// Call the appropriate function
	if (useSymlink) {
		(*cli_functions[cmdID]) (conn, argc, &argv[0]);
	}else {
		(*cli_functions[cmdID]) (conn, argc-1, &argv[1]);
	}

	// Disconnect from the backend
	if (!needCommandHelp) {
		ucart_backendDisconnect(conn);
	}
    return 0;
}


/* This function is called by other cli functions to check for a help condition */
int help_check(int argc, char ** argv) {
	int c;
	static int needHelp = 0;
	static struct option long_options[] = {
 		/* These options don’t set a flag. We distinguish them by their indices. */
 		{"help",	no_argument,	&needHelp,	1},
 		{0, 0, 0, 0}
 	};

 	while (1)
	{
		/* getopt_long stores the option index here. */
		int option_index = 0;

		c = getopt_long(argc, argv, "h", long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		if (c == 'h') {
			needHelp = 1;
		}
	}
	return needHelp;
}