Created
May 31, 2020 04:56
-
-
Save td-shi/ff29a3d43f4aeaacac588076c210e856 to your computer and use it in GitHub Desktop.
Template of CLI application for linux shell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //(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