"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/isc/commandline.c" (4 Sep 2020, 7037 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "commandline.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*
   13  * Copyright (c) 1987, 1993, 1994
   14  *  The Regents of the University of California.  All rights reserved.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  */
   40 
   41 /*! \file
   42  * This file was adapted from the NetBSD project's source tree, RCS ID:
   43  *    NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
   44  *
   45  * The primary change has been to rename items to the ISC namespace
   46  * and format in the ISC coding style.
   47  */
   48 
   49 #include <stdbool.h>
   50 #include <stdio.h>
   51 
   52 #include <isc/commandline.h>
   53 #include <isc/mem.h>
   54 #include <isc/print.h>
   55 #include <isc/string.h>
   56 #include <isc/util.h>
   57 
   58 /*% Index into parent argv vector. */
   59 LIBISC_EXTERNAL_DATA int isc_commandline_index = 1;
   60 /*% Character checked for validity. */
   61 LIBISC_EXTERNAL_DATA int isc_commandline_option;
   62 /*% Argument associated with option. */
   63 LIBISC_EXTERNAL_DATA char *isc_commandline_argument;
   64 /*% For printing error messages. */
   65 LIBISC_EXTERNAL_DATA char *isc_commandline_progname;
   66 /*% Print error messages. */
   67 LIBISC_EXTERNAL_DATA bool isc_commandline_errprint = true;
   68 /*% Reset processing. */
   69 LIBISC_EXTERNAL_DATA bool isc_commandline_reset = true;
   70 
   71 static char endopt = '\0';
   72 
   73 #define BADOPT '?'
   74 #define BADARG ':'
   75 #define ENDOPT &endopt
   76 
   77 /*!
   78  * getopt --
   79  *  Parse argc/argv argument vector.
   80  */
   81 int
   82 isc_commandline_parse(int argc, char *const *argv, const char *options) {
   83     static char *place = ENDOPT;
   84     const char *option; /* Index into *options of option. */
   85 
   86     REQUIRE(argc >= 0 && argv != NULL && options != NULL);
   87 
   88     /*
   89      * Update scanning pointer, either because a reset was requested or
   90      * the previous argv was finished.
   91      */
   92     if (isc_commandline_reset || *place == '\0') {
   93         if (isc_commandline_reset) {
   94             isc_commandline_index = 1;
   95             isc_commandline_reset = false;
   96         }
   97 
   98         if (isc_commandline_progname == NULL) {
   99             isc_commandline_progname = argv[0];
  100         }
  101 
  102         if (isc_commandline_index >= argc ||
  103             *(place = argv[isc_commandline_index]) != '-')
  104         {
  105             /*
  106              * Index out of range or points to non-option.
  107              */
  108             place = ENDOPT;
  109             return (-1);
  110         }
  111 
  112         if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
  113             /*
  114              * Found '--' to signal end of options.  Advance
  115              * index to next argv, the first non-option.
  116              */
  117             isc_commandline_index++;
  118             place = ENDOPT;
  119             return (-1);
  120         }
  121     }
  122 
  123     isc_commandline_option = *place++;
  124     option = strchr(options, isc_commandline_option);
  125 
  126     /*
  127      * Ensure valid option has been passed as specified by options string.
  128      * '-:' is never a valid command line option because it could not
  129      * distinguish ':' from the argument specifier in the options string.
  130      */
  131     if (isc_commandline_option == ':' || option == NULL) {
  132         if (*place == '\0') {
  133             isc_commandline_index++;
  134         }
  135 
  136         if (isc_commandline_errprint && *options != ':') {
  137             fprintf(stderr, "%s: illegal option -- %c\n",
  138                 isc_commandline_progname,
  139                 isc_commandline_option);
  140         }
  141 
  142         return (BADOPT);
  143     }
  144 
  145     if (*++option != ':') {
  146         /*
  147          * Option does not take an argument.
  148          */
  149         isc_commandline_argument = NULL;
  150 
  151         /*
  152          * Skip to next argv if at the end of the current argv.
  153          */
  154         if (*place == '\0') {
  155             ++isc_commandline_index;
  156         }
  157     } else {
  158         /*
  159          * Option needs an argument.
  160          */
  161         if (*place != '\0') {
  162             /*
  163              * Option is in this argv, -D1 style.
  164              */
  165             isc_commandline_argument = place;
  166         } else if (argc > ++isc_commandline_index) {
  167             /*
  168              * Option is next argv, -D 1 style.
  169              */
  170             isc_commandline_argument = argv[isc_commandline_index];
  171         } else {
  172             /*
  173              * Argument needed, but no more argv.
  174              */
  175             place = ENDOPT;
  176 
  177             /*
  178              * Silent failure with "missing argument" return
  179              * when ':' starts options string, per historical spec.
  180              */
  181             if (*options == ':') {
  182                 return (BADARG);
  183             }
  184 
  185             if (isc_commandline_errprint) {
  186                 fprintf(stderr,
  187                     "%s: option requires an argument -- "
  188                     "%c\n",
  189                     isc_commandline_progname,
  190                     isc_commandline_option);
  191             }
  192 
  193             return (BADOPT);
  194         }
  195 
  196         place = ENDOPT;
  197 
  198         /*
  199          * Point to argv that follows argument.
  200          */
  201         isc_commandline_index++;
  202     }
  203 
  204     return (isc_commandline_option);
  205 }
  206 
  207 isc_result_t
  208 isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp,
  209               char ***argvp, unsigned int n) {
  210     isc_result_t result;
  211 
  212 restart:
  213     /* Discard leading whitespace. */
  214     while (*s == ' ' || *s == '\t') {
  215         s++;
  216     }
  217 
  218     if (*s == '\0') {
  219         /* We have reached the end of the string. */
  220         *argcp = n;
  221         *argvp = isc_mem_get(mctx, n * sizeof(char *));
  222     } else {
  223         char *p = s;
  224         while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') {
  225             if (*p == '\n') {
  226                 *p = ' ';
  227                 goto restart;
  228             }
  229             p++;
  230         }
  231 
  232         /* do "grouping", items between { and } are one arg */
  233         if (*p == '{') {
  234             char *t = p;
  235             /*
  236              * shift all characters to left by 1 to get rid of '{'
  237              */
  238             while (*t != '\0') {
  239                 t++;
  240                 *(t - 1) = *t;
  241             }
  242             while (*p != '\0' && *p != '}') {
  243                 p++;
  244             }
  245             /* get rid of '}' character */
  246             if (*p == '}') {
  247                 *p = '\0';
  248                 p++;
  249             }
  250             /* normal case, no "grouping" */
  251         } else if (*p != '\0') {
  252             *p++ = '\0';
  253         }
  254 
  255         result = isc_commandline_strtoargv(mctx, p, argcp, argvp,
  256                            n + 1);
  257         if (result != ISC_R_SUCCESS) {
  258             return (result);
  259         }
  260         (*argvp)[n] = s;
  261     }
  262 
  263     return (ISC_R_SUCCESS);
  264 }