1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 
22 
23 extern void handle_usage_help(FILE *out_fp, const char *prog_name);
24 extern int handle_command_help(int argc, char *argv[], int arg_start);
25 extern void handle_usage_dump(FILE *out_fp, const char *prog_name);
26 extern int handle_command_dump(int argc, char *argv[], int arg_start);
27 extern void handle_usage_create(FILE *out_fp, const char *prog_name);
28 extern int handle_command_create(int argc, char *argv[], int arg_start);
29 extern void handle_usage_cfg_create(FILE *out_fp, const char *prog_name);
30 extern int handle_command_cfg_create(int argc, char *argv[], int arg_start);
31 
32 
33 struct command_info {
34   const char *command;
35   void (*usage)(FILE *out_fp, const char *prog_name);
36   int (*handler)(int argc, char *argv[], int arg_start);
37 };
38 
39 static const struct command_info command_infos[] = {
40   { "help", handle_usage_help, handle_command_help },
41   { "dump", handle_usage_dump, handle_command_dump },
42   { "create", handle_usage_create, handle_command_create },
43   { "cfg_create", handle_usage_cfg_create, handle_command_cfg_create },
44   { NULL, NULL, NULL }
45 };
46 
search_command(const char * command)47 static const struct command_info *search_command(const char *command) {
48   const struct command_info *info;
49   for (info = command_infos; info->command != NULL; info++) {
50     if (strcmp(command, info->command) == 0) {
51       break;
52     }
53   }
54   if (info->command == NULL) {
55     fprintf(stderr, "Unknown command: %s\n", command);
56     return NULL;
57   }
58   return info;
59 }
60 
print_all_commands(FILE * out_fp)61 static void print_all_commands(FILE *out_fp) {
62   const struct command_info *info;
63   for (info = command_infos; info->command != NULL; info++) {
64     if (info != command_infos) {
65       fprintf(out_fp, ", ");
66     }
67     fprintf(out_fp, "%s", info->command);
68   }
69   fprintf(out_fp, "\n");
70 }
71 
output_all_usage(FILE * out_fp,const char * prog_name)72 static void output_all_usage(FILE *out_fp, const char *prog_name) {
73   fprintf(out_fp, "  %s <command>\n\n", prog_name);
74   fprintf(out_fp, "    commands:\n      ");
75   print_all_commands(out_fp);
76   fprintf(out_fp, "\n");
77 
78   const struct command_info *info;
79   for (info = command_infos; info->command != NULL; info++) {
80     info->usage(out_fp, prog_name);
81     fprintf(out_fp, "\n");
82   }
83 }
84 
handle_usage_help(FILE * out_fp,const char * prog_name)85 void handle_usage_help(FILE *out_fp, const char *prog_name) {
86   fprintf(out_fp, "  %s help all\n", prog_name);
87   fprintf(out_fp, "  %s help <command>\n\n", prog_name);
88   fprintf(out_fp, "    commands:\n      ");
89   print_all_commands(out_fp);
90 }
91 
handle_command_help(int argc,char * argv[],int arg_start)92 int handle_command_help(int argc, char *argv[], int arg_start) {
93   const char *prog_name = argv[0];
94 
95   if (argc - arg_start < 1) {
96     handle_usage_help(stderr, prog_name);
97     return 1;
98   }
99 
100   if (strcmp(argv[arg_start], "all") == 0) {
101     output_all_usage(stdout, prog_name);
102     return 0;
103   }
104 
105   const struct command_info *info = search_command(argv[arg_start]);
106   if (info == NULL) {
107     handle_usage_help(stderr, prog_name);
108     return 1;
109   }
110 
111   info->usage(stdout, prog_name);
112 
113   return 0;
114 }
115 
main(int argc,char * argv[])116 int main(int argc, char *argv[]) {
117   if (argc <= 1) {
118     output_all_usage(stderr, argv[0]);
119     return 1;
120   }
121 
122   const char *command = argv[1];
123   const struct command_info *info = search_command(command);
124   if (info == NULL) {
125     return 1;
126   }
127 
128   /* skip 2 arguments, argv[0] and argv[1] */
129   return info->handler(argc, argv, 2);
130 }
131