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     struct option *long_options = (struct option *)
     33             calloc(count, sizeof(struct option));
     34     for (int i = 0; options[i].longName; i++) {
     35         long_options[i].name = options[i].longName;
     36         long_options[i].flag = 0;
     37 
     38         if (!options[i].val) {
     39             fprintf(stderr, __FILE__ ": val required\n");
     40             abort();
     41         }
     42         long_options[i].val = options[i].val;
     43 
     44         switch (options[i].argInfo) {
     45         case POPT_ARG_NONE:
     46             long_options[i].has_arg = no_argument;
     47             break;
     48         case POPT_ARG_STRING:
     49         case POPT_ARG_INT:
     50             if (!options[i].arg) {
     51                 fprintf(stderr, __FILE__ ": arg required\n");
     52                 abort();
     53             }
     54             long_options[i].has_arg = required_argument;
     55             break;
     56         default:
     57             fprintf(stderr, __FILE__ ": unsupported argInfo\n");
     58             abort();
     59         }
     60     }
     61 
     62     poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext));
     63     con->argc = argc;
     64     con->argv = argv;
     65     con->options = options;
     66     con->long_options = long_options;
     67     return con;
     68 }
     69 
     70 poptContext poptFreeContext(poptContext con) {
     71     free(con->long_options);
     72     free(con);
     73     return 0;
     74 }
     75 
     76 void poptResetContext(poptContext con) {
     77     optind = 1;
     78 }
     79 
     80 void poptSetOtherOptionHelp(poptContext con, const char *text) {
     81     con->otherHelp = text;
     82 }
     83 
     84 void poptPrintUsage(poptContext con, FILE *fp, int flags) {
     85     fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp);
     86     int i = 0;
     87     for (; con->options[i].longName; i++) {
     88         fprintf(fp, "\t--%s\t%s\n", con->options[i].longName,
     89                 con->options[i].descrip);
     90     }
     91     fprintf(fp, "\n");
     92 }
     93 
     94 int poptGetNextOpt(poptContext con) {
     95     int i = -1;
     96     int res = getopt_long(con->argc, (char *const *) con->argv, "",
     97             con->long_options, &i);
     98 #ifdef LOCAL_DEBUG
     99     fprintf(stderr, "getopt_long()=%c\n", res);
    100 #endif
    101     if (res <= 0 || res == '?' || i == -1) {
    102         return -1;
    103     }
    104 
    105     // Copy over found argument value
    106     switch (con->options[i].argInfo) {
    107     case POPT_ARG_STRING:
    108         *((char**) con->options[i].arg) = strdup(optarg);
    109         break;
    110     case POPT_ARG_INT:
    111         *((int*) con->options[i].arg) = atoi(optarg);
    112         break;
    113     }
    114 
    115     return res;
    116 }
    117 
    118 const char *poptGetArg(poptContext con) {
    119     const char *res = con->argv[optind++];
    120 #ifdef LOCAL_DEBUG
    121     fprintf(stderr, "poptGetArg()=%s\n", res);
    122 #endif
    123     return res;
    124 }
    125