Skip to content

Instantly share code, notes, and snippets.

@td-shi
Created May 31, 2020 04:56
Show Gist options
  • Select an option

  • Save td-shi/ff29a3d43f4aeaacac588076c210e856 to your computer and use it in GitHub Desktop.

Select an option

Save td-shi/ff29a3d43f4aeaacac588076c210e856 to your computer and use it in GitHub Desktop.
Template of CLI application for linux shell
//(1)=========================================================<< File Header >>=
/**
* @file c-template_linux_cli_application.c
* @brief <Application meaning> Ver 0.01
* @author TD
* @date 2020-05-31
*
* <pre> 2020 TD LICENSED CC0 </pre>
******************************************************************************/
//(2)======================================================<< System Include >>=
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
//(3)========================================================<< User Include >>=
//(4)========================================================<< Local Macros >>=
#define CLI_BUF_SZ (64)
#define VERSION ("0.01")
#define VERSION_DATE ("2020-05-31")
#define VERSION_TIME ("14:00")
//(5)===============================================<< Local Macro Functions >>=
//(6)==================================================<< Local Type defines >>=
//(7)==================================================<< Local Enum defines >>=
//(8)==================================================<< Local Suruct/Union >>=
typedef struct _configure{
int (*check)(char*);
int (*act)(char*);
const struct _configure* next;
}CONFIGURE;
//(9)===================================================<< Forward reference >>=
// utility
static int isDiff(const char* reference, const char* target);
// judge option argment
static int isHelp(char* arg);
static int isUnknownOption(char* arg);
// act option argment
static int actShowHelp(char* arg);
// application main
static int parseArgs(int argc, char *argv[]);
static int runConsoleTop(void);
static int runPipline(void);
//(10)===================================================<< Static variables >>=
// state machine for option argment
static const CONFIGURE argments[] = {
{&isHelp, &actShowHelp, argments},
{&isUnknownOption, &actShowHelp, argments} // Always the end of table.
};
// option configure values
static char* s_OwnName = NULL;
//(11)===================================================<< Static functions >>=
/* @brief Is the string difference.
* @param target option string
* @return 0: no !0: yes and value
*****************************************************************************/
static int isDiff(const char* reference, const char* target)
{
while(('\0' != *reference) && ('\0' != *target) && (*reference == *target)){
reference++;
target++;
}
return (unsigned char)*reference - (unsigned char)*target;
}
/* @brief Is the option showing help.
* @param arg option string
* @return 0: no !0: yes
*****************************************************************************/
static int isHelp(char* arg)
{
int ret = 0;
if(0 != isDiff("-h", arg)){
ret = 1;
}
else if(0 != isDiff("--help", arg)){
ret = 1;
}
else if(0 != isDiff("-v", arg)){
ret = 1;
}
else if(0 != isDiff("--version", arg)){
ret = 1;
}
else{
ret = 0;
}
return ret;
}
/* @brief Always true.
* @param arg option string. but not use.
* @return 0: no !0: yes
*****************************************************************************/
static int isUnknownOption(char* arg)
{
arg = NULL;
return 1;
}
/* @brief Show the help string.
* @param arg option string. but not use.
* @return 0: no error !0: error
*****************************************************************************/
static int actShowHelp(char* arg)
{
arg = NULL;
fprintf(stderr, "# About\n\n");
fprintf(stderr, "The %s is a shell application based on POSIX.\n", s_OwnName);
fprintf(stderr, "<Description>\n\n");
fprintf(stderr, "# Usage\n\n## Command\n\n");
fprintf(stderr, "%s [Options]\n", s_OwnName);
fprintf(stderr, "\n");
fprintf(stderr, "## Options\n\n");
fprintf(stderr, "+ -h |--help |-v |--version\n - Show this help.\n");
fprintf(stderr, "\n");
fprintf(stderr, "# Version\n\n%sT%s %s\n\n", VERSION_DATE, VERSION_TIME, VERSION);
fprintf(stderr, "# LICENSE\n\n[CC0(Public domain)](https://creativecommons.org/publicdomain/zero/1.0/legalcode)\n\n");
fprintf(stderr, "# Author\n\n2020 TD\n");
return 1;
}
/* @brief parsing argments.
* @param argc numbers of argments.
* @param argv argment head.
* @return 0: no error !0: error
*****************************************************************************/
static int parseArgs(int argc, char *argv[])
{
size_t option = 0;
const CONFIGURE* decision = argments;
s_OwnName = argv[option];
for(option = 1; argc > option; option++){
while(0 == decision->check(argv[option])){
decision++;
}
if(decision->act(argv[option])){
return 1;
}
decision = decision->next;
}
return 0;
}
/* @brief shell run from console.
* @return 0: no error !0: error
* @note The option reference to global values.
*****************************************************************************/
static int runConsoleTop(void)
{
int ret = 0;
ret = actShowHelp(NULL);
return ret;
}
/* @brief shell run from pipline.
* @return 0: no error !0: error
* @note The option reference to global values.
*****************************************************************************/
static int runPipline(void)
{
int ret = 0;
ssize_t length = 0;
char* buffer = NULL;
while(!(feof(stdin))){
length = getline(&buffer, &(size_t){CLI_BUF_SZ}, stdin);
if(0 < length){
printf("%s", buffer);
}
}
free(buffer);
return ret;
}
//(12)===================================================<< Global variables >>=
//(13)===================================================<< Function defines >>=
/* @brief shell command body.
* @param argc numbers of argments.
* @param argv argment head
* @return 0: no error !0: error
*****************************************************************************/
int main(int argc, char *argv[])
{
int ret = 0;
ret = parseArgs(argc, argv);
if(0 != ret){
;
}
else if(isatty(fileno(stdin))){
ret = runConsoleTop();
}
else{
ret = runPipline();
}
return ret;
}
//(14)==========================================================<< Chage Log >>=
//(15)========================================================<< End Of File >>=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment