1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 1991 Keith Muller. 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Keith Muller of the University of California, San Diego. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40 #if 0 41 #ifndef lint 42 static char sccsid[] = "@(#)egetopt.c 8.1 (Berkeley) 6/6/93"; 43 #endif /* not lint */ 44 #endif 45 46 #include <sys/cdefs.h> 47 __FBSDID("$FreeBSD$"); 48 49 #include <ctype.h> 50 #include <stdio.h> 51 #include <string.h> 52 53 #include "extern.h" 54 55 /* 56 * egetopt: get option letter from argument vector (an extended 57 * version of getopt). 58 * 59 * Non standard additions to the ostr specs are: 60 * 1) '?': immediate value following arg is optional (no white space 61 * between the arg and the value) 62 * 2) '#': +/- followed by a number (with an optional sign but 63 * no white space between the arg and the number). The - may be 64 * combined with other options, but the + cannot. 65 */ 66 67 int eopterr = 1; /* if error message should be printed */ 68 int eoptind = 1; /* index into parent argv vector */ 69 int eoptopt; /* character checked for validity */ 70 char *eoptarg; /* argument associated with option */ 71 72 #define BADCH (int)'?' 73 74 static char emsg[] = ""; 75 76 int 77 egetopt(int nargc, char * const *nargv, const char *ostr) 78 { 79 static char *place = emsg; /* option letter processing */ 80 char *oli; /* option letter list index */ 81 static int delim; /* which option delimiter */ 82 char *p; 83 static char savec = '\0'; 84 85 if (savec != '\0') { 86 *place = savec; 87 savec = '\0'; 88 } 89 90 if (!*place) { 91 /* 92 * update scanning pointer 93 */ 94 if ((eoptind >= nargc) || 95 ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) { 96 place = emsg; 97 return (-1); 98 } 99 100 delim = (int)*place; 101 if (place[1] && *++place == '-' && !place[1]) { 102 /* 103 * found "--" 104 */ 105 ++eoptind; 106 place = emsg; 107 return (-1); 108 } 109 } 110 111 /* 112 * check option letter 113 */ 114 if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') || 115 !(oli = strchr(ostr, eoptopt))) { 116 /* 117 * if the user didn't specify '-' as an option, 118 * assume it means -1 when by itself. 119 */ 120 if ((eoptopt == (int)'-') && !*place) 121 return (-1); 122 if (strchr(ostr, '#') && (isdigit(eoptopt) || 123 (((eoptopt == (int)'-') || (eoptopt == (int)'+')) && 124 isdigit(*place)))) { 125 /* 126 * # option: +/- with a number is ok 127 */ 128 for (p = place; *p != '\0'; ++p) { 129 if (!isdigit(*p)) 130 break; 131 } 132 eoptarg = place-1; 133 134 if (*p == '\0') { 135 place = emsg; 136 ++eoptind; 137 } else { 138 place = p; 139 savec = *p; 140 *place = '\0'; 141 } 142 return (delim); 143 } 144 145 if (!*place) 146 ++eoptind; 147 if (eopterr) { 148 if (!(p = strrchr(*nargv, '/'))) 149 p = *nargv; 150 else 151 ++p; 152 (void)fprintf(stderr, "%s: illegal option -- %c\n", 153 p, eoptopt); 154 } 155 return (BADCH); 156 } 157 if (delim == (int)'+') { 158 /* 159 * '+' is only allowed with numbers 160 */ 161 if (!*place) 162 ++eoptind; 163 if (eopterr) { 164 if (!(p = strrchr(*nargv, '/'))) 165 p = *nargv; 166 else 167 ++p; 168 (void)fprintf(stderr, 169 "%s: illegal '+' delimiter with option -- %c\n", 170 p, eoptopt); 171 } 172 return (BADCH); 173 } 174 ++oli; 175 if ((*oli != ':') && (*oli != '?')) { 176 /* 177 * don't need argument 178 */ 179 eoptarg = NULL; 180 if (!*place) 181 ++eoptind; 182 return (eoptopt); 183 } 184 185 if (*place) { 186 /* 187 * no white space 188 */ 189 eoptarg = place; 190 } else if (*oli == '?') { 191 /* 192 * no arg, but NOT required 193 */ 194 eoptarg = NULL; 195 } else if (nargc <= ++eoptind) { 196 /* 197 * no arg, but IS required 198 */ 199 place = emsg; 200 if (eopterr) { 201 if (!(p = strrchr(*nargv, '/'))) 202 p = *nargv; 203 else 204 ++p; 205 (void)fprintf(stderr, 206 "%s: option requires an argument -- %c\n", p, 207 eoptopt); 208 } 209 return (BADCH); 210 } else { 211 /* 212 * arg has white space 213 */ 214 eoptarg = nargv[eoptind]; 215 } 216 place = emsg; 217 ++eoptind; 218 return (eoptopt); 219 } 220