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 }