00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "libts.h"
00030
00031
00032
00033
00034
00035 const char *file_arguments[MAX_FILE_ARGUMENTS] = { 0 };
00036 const char *program_name = (char *) "Traffic Server";
00037 unsigned n_file_arguments = 0;
00038
00039
00040
00041
00042
00043 static const char *argument_types_keys = (char *) "ISDfFTL";
00044 static const char *argument_types_descriptions[] = {
00045 (char *) "int ",
00046 (char *) "str ",
00047 (char *) "dbl ",
00048 (char *) "off ",
00049 (char *) "on ",
00050 (char *) "tog ",
00051 (char *) "i64 ",
00052 (char *) " "
00053 };
00054
00055
00056
00057
00058
00059 static void
00060 process_arg(const ArgumentDescription * argument_descriptions,
00061 unsigned n_argument_descriptions, int i, char ***argv, const char *usage_string)
00062 {
00063 char *arg = NULL;
00064 if (argument_descriptions[i].type) {
00065 char type = argument_descriptions[i].type[0];
00066 if (type == 'F' || type == 'f')
00067 *(int *) argument_descriptions[i].location = type == 'F' ? 1 : 0;
00068 else if (type == 'T')
00069 *(int *) argument_descriptions[i].location = !*(int *) argument_descriptions[i].location;
00070 else {
00071 arg = *++(**argv) ? **argv : *++(*argv);
00072 if (!arg)
00073 usage(argument_descriptions, n_argument_descriptions, usage_string);
00074 switch (type) {
00075 case 'I':
00076 *(int *) argument_descriptions[i].location = atoi(arg);
00077 break;
00078 case 'D':
00079 *(double *) argument_descriptions[i].location = atof(arg);
00080 break;
00081 case 'L':
00082 *(int64_t *) argument_descriptions[i].location = ink_atoi64(arg);
00083 break;
00084 case 'S':
00085 if (argument_descriptions[i].type[1] == '*') {
00086 char ** out = (char **)argument_descriptions[i].location;
00087 *out = ats_strdup(arg);
00088 } else {
00089 ink_strlcpy((char *) argument_descriptions[i].location, arg, atoi(argument_descriptions[i].type + 1));
00090 }
00091 break;
00092 default:
00093 ink_fatal(1, (char *) "bad argument description");
00094 break;
00095 }
00096 **argv += strlen(**argv) - 1;
00097 }
00098 }
00099 if (argument_descriptions[i].pfn)
00100 argument_descriptions[i].pfn(argument_descriptions, n_argument_descriptions, arg);
00101 }
00102
00103
00104 void
00105 show_argument_configuration(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions)
00106 {
00107 printf("Argument Configuration\n");
00108 for (unsigned i = 0; i < n_argument_descriptions; i++) {
00109 if (argument_descriptions[i].type) {
00110 printf(" %-34s ", argument_descriptions[i].description);
00111 switch (argument_descriptions[i].type[0]) {
00112 case 'F':
00113 case 'f':
00114 case 'T':
00115 printf(*(int *) argument_descriptions[i].location ? "TRUE" : "FALSE");
00116 break;
00117 case 'I':
00118 printf("%d", *(int *) argument_descriptions[i].location);
00119 break;
00120 case 'D':
00121 printf("%f", *(double *) argument_descriptions[i].location);
00122 break;
00123 case 'L':
00124 printf("%" PRId64 "", *(int64_t *) argument_descriptions[i].location);
00125 break;
00126 case 'S':
00127 printf("%s", (char *) argument_descriptions[i].location);
00128 break;
00129 default:
00130 ink_fatal(1, (char *) "bad argument description");
00131 break;
00132 }
00133 printf("\n");
00134 }
00135 }
00136 }
00137
00138 void
00139 process_args(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, char **argv, const char *usage_string)
00140 {
00141 unsigned i = 0;
00142
00143
00144
00145 for (i = 0; i < n_argument_descriptions; i++)
00146 if (argument_descriptions[i].env) {
00147 char type = argument_descriptions[i].type[0];
00148 char *env = getenv(argument_descriptions[i].env);
00149 if (!env)
00150 continue;
00151 switch (type) {
00152 case 'f':
00153 case 'F':
00154 case 'I':
00155 *(int *) argument_descriptions[i].location = atoi(env);
00156 break;
00157 case 'D':
00158 *(double *) argument_descriptions[i].location = atof(env);
00159 break;
00160 case 'L':
00161 *(int64_t *) argument_descriptions[i].location = atoll(env);
00162 break;
00163 case 'S':
00164 ink_strlcpy((char *) argument_descriptions[i].location, env, atoi(argument_descriptions[i].type + 1));
00165 break;
00166 }
00167 }
00168
00169
00170
00171 program_name = argv[0];
00172 while (*++argv) {
00173 if (**argv == '-') {
00174 if ((*argv)[1] == '-') {
00175 for (i = 0; i < n_argument_descriptions; i++)
00176 if (!strcmp(argument_descriptions[i].name, (*argv) + 2)) {
00177 *argv += strlen(*argv) - 1;
00178 process_arg(argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
00179 break;
00180 }
00181 if (i >= n_argument_descriptions)
00182 usage(argument_descriptions, n_argument_descriptions, usage_string);
00183 } else {
00184 while (*++(*argv))
00185 for (i = 0; i < n_argument_descriptions; i++)
00186 if (argument_descriptions[i].key == **argv) {
00187 process_arg(argument_descriptions, n_argument_descriptions, i, &argv, usage_string);
00188 break;
00189 }
00190 if (i >= n_argument_descriptions)
00191 usage(argument_descriptions, n_argument_descriptions, usage_string);
00192 }
00193 } else {
00194 if (n_file_arguments >= countof(file_arguments)) {
00195 ink_fatal(1, "too many files");
00196 }
00197 file_arguments[n_file_arguments++] = *argv;
00198 file_arguments[n_file_arguments] = NULL;
00199 }
00200 }
00201 }
00202
00203 void
00204 usage(const ArgumentDescription * argument_descriptions, unsigned n_argument_descriptions, const char *usage_string)
00205 {
00206 (void) argument_descriptions;
00207 (void) n_argument_descriptions;
00208 (void) usage_string;
00209 if (usage_string)
00210 fprintf(stderr, "%s\n", usage_string);
00211 else
00212 fprintf(stderr, "Usage: %s [--SWITCH [ARG]]\n", program_name);
00213 fprintf(stderr, " switch__________________type__default___description\n");
00214 for (unsigned i = 0; i < n_argument_descriptions; i++) {
00215 if (!argument_descriptions[i].description)
00216 continue;
00217
00218 fprintf(stderr, " ");
00219
00220 if ('-' == argument_descriptions[i].key) fprintf(stderr, " ");
00221 else fprintf(stderr, "-%c,", argument_descriptions[i].key);
00222
00223 fprintf(stderr, " --%-17s %s",
00224 argument_descriptions[i].name,
00225 argument_types_descriptions[argument_descriptions[i].type ?
00226 strchr(argument_types_keys,
00227 argument_descriptions[i].type[0]) -
00228 argument_types_keys : strlen(argument_types_keys)
00229 ]);
00230 switch (argument_descriptions[i].type ? argument_descriptions[i].type[0] : 0) {
00231 case 0:
00232 fprintf(stderr, " ");
00233 break;
00234 case 'L':
00235 fprintf(stderr, " %-9" PRId64 "", *(int64_t *) argument_descriptions[i].location);
00236 break;
00237 case 'S':
00238 if (*(char *) argument_descriptions[i].location) {
00239 if (strlen((char *) argument_descriptions[i].location) < 10)
00240 fprintf(stderr, " %-9s", (char *) argument_descriptions[i].location);
00241 else {
00242 ((char *) argument_descriptions[i].location)[7] = 0;
00243 fprintf(stderr, " %-7s..", (char *) argument_descriptions[i].location);
00244 }
00245 } else
00246 fprintf(stderr, " (null) ");
00247 break;
00248 case 'D':
00249 fprintf(stderr, " %-9.3f", *(double *) argument_descriptions[i].location);
00250 break;
00251 case 'I':
00252 fprintf(stderr, " %-9d", *(int *) argument_descriptions[i].location);
00253 break;
00254 case 'T':
00255 case 'f':
00256 case 'F':
00257 fprintf(stderr, " %-9s", *(int *) argument_descriptions[i].location ? "true " : "false");
00258 break;
00259 }
00260 fprintf(stderr, " %s\n", argument_descriptions[i].description);
00261 }
00262 _exit(1);
00263 }