commandline.c revision 290001
1/* 2 * Portions Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") 3 * Portions Copyright (C) 1999-2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * Copyright (c) 1987, 1993, 1994 20 * The Regents of the University of California. All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * This product includes software developed by the University of 33 * California, Berkeley and its contributors. 34 * 4. Neither the name of the University nor the names of its contributors 35 * may be used to endorse or promote products derived from this software 36 * without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 */ 50 51/* $Id: commandline.c,v 1.22 2008/09/25 04:02:39 tbox Exp $ */ 52 53/*! \file 54 * This file was adapted from the NetBSD project's source tree, RCS ID: 55 * NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp 56 * 57 * The primary change has been to rename items to the ISC namespace 58 * and format in the ISC coding style. 59 */ 60 61/* 62 * \author Principal Authors: Computer Systems Research Group at UC Berkeley 63 * \author Principal ISC caretaker: DCL 64 */ 65 66#include <config.h> 67 68#include <stdio.h> 69 70#include <isc/commandline.h> 71#include <isc/msgs.h> 72#include <isc/string.h> 73#include <isc/util.h> 74 75/*% Index into parent argv vector. */ 76LIBISC_EXTERNAL_DATA int isc_commandline_index = 1; 77/*% Character checked for validity. */ 78LIBISC_EXTERNAL_DATA int isc_commandline_option; 79/*% Argument associated with option. */ 80LIBISC_EXTERNAL_DATA char *isc_commandline_argument; 81/*% For printing error messages. */ 82LIBISC_EXTERNAL_DATA char *isc_commandline_progname; 83/*% Print error messages. */ 84LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE; 85/*% Reset processing. */ 86LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE; 87 88static char endopt = '\0'; 89 90#define BADOPT '?' 91#define BADARG ':' 92#define ENDOPT &endopt 93 94/*! 95 * getopt -- 96 * Parse argc/argv argument vector. 97 */ 98int 99isc_commandline_parse(int argc, char * const *argv, const char *options) { 100 static char *place = ENDOPT; 101 char *option; /* Index into *options of option. */ 102 103 REQUIRE(argc >= 0 && argv != NULL && options != NULL); 104 105 /* 106 * Update scanning pointer, either because a reset was requested or 107 * the previous argv was finished. 108 */ 109 if (isc_commandline_reset || *place == '\0') { 110 if (isc_commandline_reset) { 111 isc_commandline_index = 1; 112 isc_commandline_reset = ISC_FALSE; 113 } 114 115 if (isc_commandline_progname == NULL) 116 isc_commandline_progname = argv[0]; 117 118 if (isc_commandline_index >= argc || 119 *(place = argv[isc_commandline_index]) != '-') { 120 /* 121 * Index out of range or points to non-option. 122 */ 123 place = ENDOPT; 124 return (-1); 125 } 126 127 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { 128 /* 129 * Found '--' to signal end of options. Advance 130 * index to next argv, the first non-option. 131 */ 132 isc_commandline_index++; 133 place = ENDOPT; 134 return (-1); 135 } 136 } 137 138 isc_commandline_option = *place++; 139 option = strchr(options, isc_commandline_option); 140 141 /* 142 * Ensure valid option has been passed as specified by options string. 143 * '-:' is never a valid command line option because it could not 144 * distinguish ':' from the argument specifier in the options string. 145 */ 146 if (isc_commandline_option == ':' || option == NULL) { 147 if (*place == '\0') 148 isc_commandline_index++; 149 150 if (isc_commandline_errprint && *options != ':') 151 fprintf(stderr, "%s: %s -- %c\n", 152 isc_commandline_progname, 153 isc_msgcat_get(isc_msgcat, 154 ISC_MSGSET_COMMANDLINE, 155 ISC_MSG_ILLEGALOPT, 156 "illegal option"), 157 isc_commandline_option); 158 159 return (BADOPT); 160 } 161 162 if (*++option != ':') { 163 /* 164 * Option does not take an argument. 165 */ 166 isc_commandline_argument = NULL; 167 168 /* 169 * Skip to next argv if at the end of the current argv. 170 */ 171 if (*place == '\0') 172 ++isc_commandline_index; 173 174 } else { 175 /* 176 * Option needs an argument. 177 */ 178 if (*place != '\0') 179 /* 180 * Option is in this argv, -D1 style. 181 */ 182 isc_commandline_argument = place; 183 184 else if (argc > ++isc_commandline_index) 185 /* 186 * Option is next argv, -D 1 style. 187 */ 188 isc_commandline_argument = argv[isc_commandline_index]; 189 190 else { 191 /* 192 * Argument needed, but no more argv. 193 */ 194 place = ENDOPT; 195 196 /* 197 * Silent failure with "missing argument" return 198 * when ':' starts options string, per historical spec. 199 */ 200 if (*options == ':') 201 return (BADARG); 202 203 if (isc_commandline_errprint) 204 fprintf(stderr, "%s: %s -- %c\n", 205 isc_commandline_progname, 206 isc_msgcat_get(isc_msgcat, 207 ISC_MSGSET_COMMANDLINE, 208 ISC_MSG_OPTNEEDARG, 209 "option requires " 210 "an argument"), 211 isc_commandline_option); 212 213 return (BADOPT); 214 } 215 216 place = ENDOPT; 217 218 /* 219 * Point to argv that follows argument. 220 */ 221 isc_commandline_index++; 222 } 223 224 return (isc_commandline_option); 225} 226