getopt.c revision 251069
1193323Sed/*	$NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $	*/
2193323Sed
3193323Sed/*
4193323Sed * Copyright (c) 1987, 1993, 1994
5193323Sed *	The Regents of the University of California.  All rights reserved.
6193323Sed *
7193323Sed * Redistribution and use in source and binary forms, with or without
8193323Sed * modification, are permitted provided that the following conditions
9193323Sed * are met:
10193323Sed * 1. Redistributions of source code must retain the above copyright
11193323Sed *    notice, this list of conditions and the following disclaimer.
12193323Sed * 2. Redistributions in binary form must reproduce the above copyright
13193323Sed *    notice, this list of conditions and the following disclaimer in the
14193323Sed *    documentation and/or other materials provided with the distribution.
15193323Sed * 3. Neither the name of the University nor the names of its contributors
16249423Sdim *    may be used to endorse or promote products derived from this software
17249423Sdim *    without specific prior written permission.
18249423Sdim *
19249423Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21249423Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23201360Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24198090Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29193323Sed * SUCH DAMAGE.
30193323Sed */
31193323Sed
32193323Sed#if defined(LIBC_SCCS) && !defined(lint)
33193323Sedstatic char sccsid[] = "@(#)getopt.c	8.3 (Berkeley) 4/27/95";
34193323Sed#endif /* LIBC_SCCS and not lint */
35193323Sed#include <sys/cdefs.h>
36193323Sed__FBSDID("$FreeBSD: head/lib/libc/stdlib/getopt.c 251069 2013-05-28 20:57:40Z emaste $");
37193323Sed
38212904Sdim#include "namespace.h"
39193323Sed#include <stdio.h>
40193323Sed#include <stdlib.h>
41193323Sed#include <string.h>
42193323Sed#include <unistd.h>
43193323Sed#include "un-namespace.h"
44193323Sed
45193323Sed#include "libc_private.h"
46193323Sed
47193323Sedint	opterr = 1,		/* if error message should be printed */
48193323Sed	optind = 1,		/* index into parent argv vector */
49218893Sdim	optopt,			/* character checked for validity */
50218893Sdim	optreset;		/* reset getopt */
51218893Sdimchar	*optarg;		/* argument associated with option */
52218893Sdim
53218893Sdim#define	BADCH	(int)'?'
54218893Sdim#define	BADARG	(int)':'
55193323Sed#define	EMSG	""
56193323Sed
57193323Sed/*
58193323Sed * getopt --
59226633Sdim *	Parse argc/argv argument vector.
60226633Sdim */
61226633Sdimint
62226633Sdimgetopt(nargc, nargv, ostr)
63226633Sdim	int nargc;
64226633Sdim	char * const nargv[];
65193323Sed	const char *ostr;
66193323Sed{
67193323Sed	static char *place = EMSG;		/* option letter processing */
68193323Sed	char *oli;				/* option letter list index */
69193323Sed
70193323Sed	if (optreset || *place == 0) {		/* update scanning pointer */
71193323Sed		optreset = 0;
72193323Sed		place = nargv[optind];
73193323Sed		if (optind >= nargc || *place++ != '-') {
74193323Sed			/* Argument is absent or is not an option */
75193323Sed			place = EMSG;
76193323Sed			return (-1);
77193323Sed		}
78193323Sed		optopt = *place++;
79193323Sed		if (optopt == '-' && *place == 0) {
80193323Sed			/* "--" => end of options */
81193323Sed			++optind;
82193323Sed			place = EMSG;
83193323Sed			return (-1);
84193323Sed		}
85193323Sed		if (optopt == 0) {
86193323Sed			/* Solitary '-', treat as a '-' option
87193323Sed			   if the program (eg su) is looking for it. */
88193323Sed			place = EMSG;
89193323Sed			if (strchr(ostr, '-') == NULL)
90193323Sed				return (-1);
91193323Sed			optopt = '-';
92193323Sed		}
93193323Sed	} else
94193323Sed		optopt = *place++;
95193323Sed
96218893Sdim	/* See if option letter is one the caller wanted... */
97218893Sdim	if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
98193323Sed		if (*place == 0)
99193323Sed			++optind;
100193323Sed		if (opterr && *ostr != ':')
101193323Sed			(void)fprintf(stderr,
102193323Sed			    "%s: illegal option -- %c\n", _getprogname(),
103193323Sed			    optopt);
104193323Sed		return (BADCH);
105218893Sdim	}
106218893Sdim
107218893Sdim	/* Does this option need an argument? */
108218893Sdim	if (oli[1] != ':') {
109193323Sed		/* don't need argument */
110193323Sed		optarg = NULL;
111218893Sdim		if (*place == 0)
112193323Sed			++optind;
113193323Sed	} else {
114193323Sed		/* Option-argument is either the rest of this argument or the
115193323Sed		   entire next argument. */
116218893Sdim		if (*place)
117193323Sed			optarg = place;
118193323Sed		else if (nargc > ++optind)
119193323Sed			optarg = nargv[optind];
120193323Sed		else {
121193323Sed			/* option-argument absent */
122193323Sed			place = EMSG;
123212904Sdim			if (*ostr == ':')
124193323Sed				return (BADARG);
125193323Sed			if (opterr)
126226633Sdim				(void)fprintf(stderr,
127226633Sdim				    "%s: option requires an argument -- %c\n",
128193323Sed				    _getprogname(), optopt);
129226633Sdim			return (BADCH);
130193323Sed		}
131193323Sed		place = EMSG;
132193323Sed		++optind;
133193323Sed	}
134193323Sed	return (optopt);			/* return option letter */
135193323Sed}
136193323Sed