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 }