11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1991 Keith Muller.
31590Srgrimes * Copyright (c) 1993
41590Srgrimes *	The Regents of the University of California.  All rights reserved.
51590Srgrimes *
61590Srgrimes * This code is derived from software contributed to Berkeley by
71590Srgrimes * Keith Muller of the University of California, San Diego.
81590Srgrimes *
91590Srgrimes * Redistribution and use in source and binary forms, with or without
101590Srgrimes * modification, are permitted provided that the following conditions
111590Srgrimes * are met:
121590Srgrimes * 1. Redistributions of source code must retain the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer.
141590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151590Srgrimes *    notice, this list of conditions and the following disclaimer in the
161590Srgrimes *    documentation and/or other materials provided with the distribution.
171590Srgrimes * 3. All advertising materials mentioning features or use of this software
181590Srgrimes *    must display the following acknowledgement:
191590Srgrimes *	This product includes software developed by the University of
201590Srgrimes *	California, Berkeley and its contributors.
211590Srgrimes * 4. Neither the name of the University nor the names of its contributors
221590Srgrimes *    may be used to endorse or promote products derived from this software
231590Srgrimes *    without specific prior written permission.
241590Srgrimes *
251590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351590Srgrimes * SUCH DAMAGE.
361590Srgrimes */
371590Srgrimes
3898552Smarkm#if 0
391590Srgrimes#ifndef lint
401590Srgrimesstatic char sccsid[] = "@(#)egetopt.c	8.1 (Berkeley) 6/6/93";
411590Srgrimes#endif /* not lint */
4298552Smarkm#endif
431590Srgrimes
4498552Smarkm#include <sys/cdefs.h>
4598552Smarkm__FBSDID("$FreeBSD$");
4698552Smarkm
471590Srgrimes#include <ctype.h>
481590Srgrimes#include <stdio.h>
491590Srgrimes#include <string.h>
501590Srgrimes
51204359Sed#include "extern.h"
52204359Sed
531590Srgrimes/*
541590Srgrimes * egetopt:	get option letter from argument vector (an extended
551590Srgrimes *		version of getopt).
561590Srgrimes *
571590Srgrimes * Non standard additions to the ostr specs are:
581590Srgrimes * 1) '?': immediate value following arg is optional (no white space
591590Srgrimes *    between the arg and the value)
601590Srgrimes * 2) '#': +/- followed by a number (with an optional sign but
611590Srgrimes *    no white space between the arg and the number). The - may be
621590Srgrimes *    combined with other options, but the + cannot.
631590Srgrimes */
641590Srgrimes
651590Srgrimesint	eopterr = 1;		/* if error message should be printed */
661590Srgrimesint	eoptind = 1;		/* index into parent argv vector */
671590Srgrimesint	eoptopt;		/* character checked for validity */
681590Srgrimeschar	*eoptarg;		/* argument associated with option */
691590Srgrimes
701590Srgrimes#define	BADCH	(int)'?'
711590Srgrimes
7298552Smarkmstatic char	emsg[] = "";
7398552Smarkm
741590Srgrimesint
7598552Smarkmegetopt(int nargc, char * const *nargv, const char *ostr)
761590Srgrimes{
7798552Smarkm	static char *place = emsg;	/* option letter processing */
7898552Smarkm	char *oli;			/* option letter list index */
79289677Seadler	static int delim;		/* which option delimiter */
8098552Smarkm	char *p;
811590Srgrimes	static char savec = '\0';
821590Srgrimes
831590Srgrimes	if (savec != '\0') {
841590Srgrimes		*place = savec;
851590Srgrimes		savec = '\0';
861590Srgrimes	}
871590Srgrimes
881590Srgrimes	if (!*place) {
891590Srgrimes		/*
901590Srgrimes		 * update scanning pointer
911590Srgrimes		 */
921590Srgrimes		if ((eoptind >= nargc) ||
931590Srgrimes		    ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
9498552Smarkm			place = emsg;
9598698Scharnier			return (-1);
961590Srgrimes		}
971590Srgrimes
981590Srgrimes		delim = (int)*place;
991590Srgrimes		if (place[1] && *++place == '-' && !place[1]) {
1001590Srgrimes			/*
1011590Srgrimes			 * found "--"
1021590Srgrimes			 */
1031590Srgrimes			++eoptind;
10498552Smarkm			place = emsg;
10598698Scharnier			return (-1);
1061590Srgrimes		}
1071590Srgrimes	}
1081590Srgrimes
1091590Srgrimes	/*
1101590Srgrimes	 * check option letter
1111590Srgrimes	 */
1121590Srgrimes	if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
1131590Srgrimes	    !(oli = strchr(ostr, eoptopt))) {
1141590Srgrimes		/*
1151590Srgrimes		 * if the user didn't specify '-' as an option,
11698698Scharnier		 * assume it means -1 when by itself.
1171590Srgrimes		 */
1181590Srgrimes		if ((eoptopt == (int)'-') && !*place)
11998698Scharnier			return (-1);
1201590Srgrimes		if (strchr(ostr, '#') && (isdigit(eoptopt) ||
1211590Srgrimes		    (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
1221590Srgrimes		      isdigit(*place)))) {
1231590Srgrimes			/*
1241590Srgrimes			 * # option: +/- with a number is ok
1251590Srgrimes			 */
1261590Srgrimes			for (p = place; *p != '\0'; ++p) {
1271590Srgrimes				if (!isdigit(*p))
1281590Srgrimes					break;
1291590Srgrimes			}
1301590Srgrimes			eoptarg = place-1;
1311590Srgrimes
1321590Srgrimes			if (*p == '\0') {
13398552Smarkm				place = emsg;
1341590Srgrimes				++eoptind;
1351590Srgrimes			} else {
1361590Srgrimes				place = p;
1371590Srgrimes				savec = *p;
1381590Srgrimes				*place = '\0';
1391590Srgrimes			}
1401590Srgrimes			return (delim);
1411590Srgrimes		}
1421590Srgrimes
1431590Srgrimes		if (!*place)
1441590Srgrimes			++eoptind;
1451590Srgrimes		if (eopterr) {
1461590Srgrimes			if (!(p = strrchr(*nargv, '/')))
1471590Srgrimes				p = *nargv;
1481590Srgrimes			else
1491590Srgrimes				++p;
1501590Srgrimes			(void)fprintf(stderr, "%s: illegal option -- %c\n",
1511590Srgrimes			    p, eoptopt);
1521590Srgrimes		}
1531590Srgrimes		return (BADCH);
1541590Srgrimes	}
1551590Srgrimes	if (delim == (int)'+') {
1561590Srgrimes		/*
1571590Srgrimes		 * '+' is only allowed with numbers
1581590Srgrimes		 */
1591590Srgrimes		if (!*place)
1601590Srgrimes			++eoptind;
1611590Srgrimes		if (eopterr) {
1621590Srgrimes			if (!(p = strrchr(*nargv, '/')))
1631590Srgrimes				p = *nargv;
1641590Srgrimes			else
1651590Srgrimes				++p;
1661590Srgrimes			(void)fprintf(stderr,
1671590Srgrimes				"%s: illegal '+' delimiter with option -- %c\n",
1681590Srgrimes				p, eoptopt);
1691590Srgrimes		}
1701590Srgrimes		return (BADCH);
1711590Srgrimes	}
1721590Srgrimes	++oli;
1731590Srgrimes	if ((*oli != ':') && (*oli != '?')) {
1741590Srgrimes		/*
1751590Srgrimes		 * don't need argument
1761590Srgrimes		 */
1771590Srgrimes		eoptarg = NULL;
1781590Srgrimes		if (!*place)
1791590Srgrimes			++eoptind;
1801590Srgrimes		return (eoptopt);
1811590Srgrimes	}
1821590Srgrimes
1831590Srgrimes	if (*place) {
1841590Srgrimes		/*
1851590Srgrimes		 * no white space
1861590Srgrimes		 */
1871590Srgrimes		eoptarg = place;
1881590Srgrimes	} else if (*oli == '?') {
1891590Srgrimes		/*
1901590Srgrimes		 * no arg, but NOT required
1911590Srgrimes		 */
1921590Srgrimes		eoptarg = NULL;
1931590Srgrimes	} else if (nargc <= ++eoptind) {
1941590Srgrimes		/*
1951590Srgrimes		 * no arg, but IS required
1961590Srgrimes		 */
19798552Smarkm		place = emsg;
1981590Srgrimes		if (eopterr) {
1991590Srgrimes			if (!(p = strrchr(*nargv, '/')))
2001590Srgrimes				p = *nargv;
2011590Srgrimes			else
2021590Srgrimes				++p;
2031590Srgrimes			(void)fprintf(stderr,
2041590Srgrimes			    "%s: option requires an argument -- %c\n", p,
2051590Srgrimes			    eoptopt);
2061590Srgrimes		}
2071590Srgrimes		return (BADCH);
2081590Srgrimes	} else {
2091590Srgrimes		/*
2101590Srgrimes		 * arg has white space
2111590Srgrimes		 */
2121590Srgrimes		eoptarg = nargv[eoptind];
2131590Srgrimes	}
21498552Smarkm	place = emsg;
2151590Srgrimes	++eoptind;
2161590Srgrimes	return (eoptopt);
2171590Srgrimes}
218