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