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