commandline.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004, 2005, 2007, 2008, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*
00019  * Copyright (c) 1987, 1993, 1994
00020  *      The Regents of the University of California.  All rights reserved.
00021  *
00022  * Redistribution and use in source and binary forms, with or without
00023  * modification, are permitted provided that the following conditions
00024  * are met:
00025  * 1. Redistributions of source code must retain the above copyright
00026  *    notice, this list of conditions and the following disclaimer.
00027  * 2. Redistributions in binary form must reproduce the above copyright
00028  *    notice, this list of conditions and the following disclaimer in the
00029  *    documentation and/or other materials provided with the distribution.
00030  * 3. Neither the name of the University nor the names of its contributors
00031  *    may be used to endorse or promote products derived from this software
00032  *    without specific prior written permission.
00033  *
00034  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00035  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00036  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00037  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00038  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00039  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00040  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00041  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00042  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00043  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00044  * SUCH DAMAGE.
00045  */
00046 
00047 /* $Id: commandline.c,v 1.22 2008/09/25 04:02:39 tbox Exp $ */
00048 
00049 /*! \file
00050  * This file was adapted from the NetBSD project's source tree, RCS ID:
00051  *    NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
00052  *
00053  * The primary change has been to rename items to the ISC namespace
00054  * and format in the ISC coding style.
00055  */
00056 
00057 /*
00058  * \author Principal Authors: Computer Systems Research Group at UC Berkeley
00059  * \author Principal ISC caretaker: DCL
00060  */
00061 
00062 #include <config.h>
00063 
00064 #include <stdio.h>
00065 
00066 #include <isc/commandline.h>
00067 #include <isc/msgs.h>
00068 #include <isc/string.h>
00069 #include <isc/util.h>
00070 
00071 /*% Index into parent argv vector. */
00072 LIBISC_EXTERNAL_DATA int isc_commandline_index = 1;
00073 /*% Character checked for validity. */
00074 LIBISC_EXTERNAL_DATA int isc_commandline_option;
00075 /*% Argument associated with option. */
00076 LIBISC_EXTERNAL_DATA char *isc_commandline_argument;
00077 /*% For printing error messages. */
00078 LIBISC_EXTERNAL_DATA char *isc_commandline_progname;
00079 /*% Print error messages. */
00080 LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE;
00081 /*% Reset processing. */
00082 LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE;
00083 
00084 static char endopt = '\0';
00085 
00086 #define BADOPT  '?'
00087 #define BADARG  ':'
00088 #define ENDOPT  &endopt
00089 
00090 /*!
00091  * getopt --
00092  *      Parse argc/argv argument vector.
00093  */
00094 int
00095 isc_commandline_parse(int argc, char * const *argv, const char *options) {
00096         static char *place = ENDOPT;
00097         char *option;                   /* Index into *options of option. */
00098 
00099         REQUIRE(argc >= 0 && argv != NULL && options != NULL);
00100 
00101         /*
00102          * Update scanning pointer, either because a reset was requested or
00103          * the previous argv was finished.
00104          */
00105         if (isc_commandline_reset || *place == '\0') {
00106                 if (isc_commandline_reset) {
00107                         isc_commandline_index = 1;
00108                         isc_commandline_reset = ISC_FALSE;
00109                 }
00110 
00111                 if (isc_commandline_progname == NULL)
00112                         isc_commandline_progname = argv[0];
00113 
00114                 if (isc_commandline_index >= argc ||
00115                     *(place = argv[isc_commandline_index]) != '-') {
00116                         /*
00117                          * Index out of range or points to non-option.
00118                          */
00119                         place = ENDOPT;
00120                         return (-1);
00121                 }
00122 
00123                 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
00124                         /*
00125                          * Found '--' to signal end of options.  Advance
00126                          * index to next argv, the first non-option.
00127                          */
00128                         isc_commandline_index++;
00129                         place = ENDOPT;
00130                         return (-1);
00131                 }
00132         }
00133 
00134         isc_commandline_option = *place++;
00135         option = strchr(options, isc_commandline_option);
00136 
00137         /*
00138          * Ensure valid option has been passed as specified by options string.
00139          * '-:' is never a valid command line option because it could not
00140          * distinguish ':' from the argument specifier in the options string.
00141          */
00142         if (isc_commandline_option == ':' || option == NULL) {
00143                 if (*place == '\0')
00144                         isc_commandline_index++;
00145 
00146                 if (isc_commandline_errprint && *options != ':')
00147                         fprintf(stderr, "%s: %s -- %c\n",
00148                                 isc_commandline_progname,
00149                                 isc_msgcat_get(isc_msgcat,
00150                                                ISC_MSGSET_COMMANDLINE,
00151                                                ISC_MSG_ILLEGALOPT,
00152                                                "illegal option"),
00153                                 isc_commandline_option);
00154 
00155                 return (BADOPT);
00156         }
00157 
00158         if (*++option != ':') {
00159                 /*
00160                  * Option does not take an argument.
00161                  */
00162                 isc_commandline_argument = NULL;
00163 
00164                 /*
00165                  * Skip to next argv if at the end of the current argv.
00166                  */
00167                 if (*place == '\0')
00168                         ++isc_commandline_index;
00169 
00170         } else {
00171                 /*
00172                  * Option needs an argument.
00173                  */
00174                 if (*place != '\0')
00175                         /*
00176                          * Option is in this argv, -D1 style.
00177                          */
00178                         isc_commandline_argument = place;
00179 
00180                 else if (argc > ++isc_commandline_index)
00181                         /*
00182                          * Option is next argv, -D 1 style.
00183                          */
00184                         isc_commandline_argument = argv[isc_commandline_index];
00185 
00186                 else {
00187                         /*
00188                          * Argument needed, but no more argv.
00189                          */
00190                         place = ENDOPT;
00191 
00192                         /*
00193                          * Silent failure with "missing argument" return
00194                          * when ':' starts options string, per historical spec.
00195                          */
00196                         if (*options == ':')
00197                                 return (BADARG);
00198 
00199                         if (isc_commandline_errprint)
00200                                 fprintf(stderr, "%s: %s -- %c\n",
00201                                         isc_commandline_progname,
00202                                         isc_msgcat_get(isc_msgcat,
00203                                                        ISC_MSGSET_COMMANDLINE,
00204                                                        ISC_MSG_OPTNEEDARG,
00205                                                        "option requires "
00206                                                        "an argument"),
00207                                         isc_commandline_option);
00208 
00209                         return (BADOPT);
00210                 }
00211 
00212                 place = ENDOPT;
00213 
00214                 /*
00215                  * Point to argv that follows argument.
00216                  */
00217                 isc_commandline_index++;
00218         }
00219 
00220         return (isc_commandline_option);
00221 }

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha