Home | History | Annotate | Download | only in gptfdisk
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * This software is licensed under the terms of the GNU General Public
      5  * License version 2, as published by the Free Software Foundation, and
      6  * may be copied, distributed, and modified under those terms.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  */
     13 
     14 #include <popt.h>
     15 
     16 // #define LOCAL_DEBUG
     17 
     18 /*
     19  * popt has been deprecated for some time, and is replaced by GNOME's glib
     20  * option parser. Instead of pulling in either of those dependencies, this
     21  * stub implements just enough of popt to get things working.
     22  */
     23 
     24 poptContext poptGetContext(const char *name, int argc, const char **argv,
     25         const struct poptOption *options, unsigned int flags) {
     26     // Convert into getopt format, sanity checking our limited
     27     // capabilities along the way
     28     int count = 0;
     29     for (; options[count].longName; count++) {
     30     }
     31 
     32     // getopt_long expects the last element to be null
     33     // so allocate count + 1
     34     struct option *long_options = (struct option *)
     35             calloc(count + 1, sizeof(struct option));
     36     for (int i = 0; options[i].longName; i++) {
     37         long_options[i].name = options[i].longName;
     38         long_options[i].flag = 0;
     39 
     40         if (!options[i].val) {
     41             fprintf(stderr, __FILE__ ": val required\n");
     42             abort();
     43         }
     44         long_options[i].val = options[i].val;
     45 
     46         switch (options[i].argInfo) {
     47         case POPT_ARG_NONE:
     48             long_options[i].has_arg = no_argument;
     49             break;
     50         case POPT_ARG_STRING:
     51         case POPT_ARG_INT:
     52             if (!options[i].arg) {
     53                 fprintf(stderr, __FILE__ ": arg required\n");
     54                 abort();
     55             }
     56             long_options[i].has_arg = required_argument;
     57             break;
     58         default:
     59             fprintf(stderr, __FILE__ ": unsupported argInfo\n");
     60             abort();
     61         }
     62     }
     63 
     64     poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext));
     65     con->argc = argc;
     66     con->argv = argv;
     67     con->options = options;
     68     con->long_options = long_options;
     69     return con;
     70 }
     71 
     72 poptContext poptFreeContext(poptContext con) {
     73     free(con->long_options);
     74     free(con);
     75     return 0;
     76 }
     77 
     78 void poptResetContext(poptContext con) {
     79     optind = 1;
     80 }
     81 
     82 void poptSetOtherOptionHelp(poptContext con, const char *text) {
     83     con->otherHelp = text;
     84 }
     85 
     86 void poptPrintUsage(poptContext con, FILE *fp, int flags) {
     87     fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp);
     88     int i = 0;
     89     for (; con->options[i].longName; i++) {
     90         fprintf(fp, "\t--%s\t%s\n", con->options[i].longName,
     91                 con->options[i].descrip);
     92     }
     93     fprintf(fp, "\n");
     94 }
     95 
     96 int poptGetNextOpt(poptContext con) {
     97     int i = -1;
     98     int res = getopt_long(con->argc, (char *const *) con->argv, "",
     99             con->long_options, &i);
    100 #ifdef LOCAL_DEBUG
    101     fprintf(stderr, "getopt_long()=%c\n", res);
    102 #endif
    103     if (res <= 0 || res == '?' || i == -1) {
    104         return -1;
    105     }
    106 
    107     // Copy over found argument value
    108     switch (con->options[i].argInfo) {
    109     case POPT_ARG_STRING:
    110         *((char**) con->options[i].arg) = strdup(optarg);
    111         break;
    112     case POPT_ARG_INT:
    113         *((int*) con->options[i].arg) = atoi(optarg);
    114         break;
    115     }
    116 
    117     return res;
    118 }
    119 
    120 const char *poptGetArg(poptContext con) {
    121     const char *res = con->argv[optind++];
    122 #ifdef LOCAL_DEBUG
    123     fprintf(stderr, "poptGetArg()=%s\n", res);
    124 #endif
    125     return res;
    126 }
    127