1/*	$NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 1987, 1993, 1994
7 *	The Regents of the University of California.  All rights reserved.
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. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "namespace.h"
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39#include "un-namespace.h"
40
41#include "libc_private.h"
42
43int	opterr = 1,		/* if error message should be printed */
44	optind = 1,		/* index into parent argv vector */
45	optopt,			/* character checked for validity */
46	optreset;		/* reset getopt */
47char	*optarg;		/* argument associated with option */
48
49#define	BADCH	(int)'?'
50#define	BADARG	(int)':'
51static char EMSG[] = "";
52/*
53 * getopt --
54 *	Parse argc/argv argument vector.
55 */
56int
57getopt(int nargc, char * const nargv[], const char *ostr)
58{
59	static char *place = EMSG;		/* option letter processing */
60	char *oli;				/* option letter list index */
61
62	if (optreset || *place == 0) {		/* update scanning pointer */
63		optreset = 0;
64		place = nargv[optind];
65		if (optind >= nargc || *place++ != '-') {
66			/* Argument is absent or is not an option */
67			place = EMSG;
68			return (-1);
69		}
70		optopt = *place++;
71		if (optopt == '-' && *place == 0) {
72			/* "--" => end of options */
73			++optind;
74			place = EMSG;
75			return (-1);
76		}
77		if (optopt == 0) {
78			/* Solitary '-', treat as a '-' option
79			   if the program (eg su) is looking for it. */
80			place = EMSG;
81			if (strchr(ostr, '-') == NULL)
82				return (-1);
83			optopt = '-';
84		}
85	} else
86		optopt = *place++;
87
88	/* See if option letter is one the caller wanted... */
89	if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
90		if (*place == 0)
91			++optind;
92		if (opterr && *ostr != ':')
93			(void)fprintf(stderr,
94			    "%s: illegal option -- %c\n", _getprogname(),
95			    optopt);
96		return (BADCH);
97	}
98
99	/* Does this option need an argument? */
100	if (oli[1] != ':') {
101		/* don't need argument */
102		optarg = NULL;
103		if (*place == 0)
104			++optind;
105	} else {
106		/* Option-argument is either the rest of this argument or the
107		   entire next argument. */
108		if (*place)
109			optarg = place;
110		else if (oli[2] == ':')
111			/*
112			 * GNU Extension, for optional arguments if the rest of
113			 * the argument is empty, we return NULL
114			 */
115			optarg = NULL;
116		else if (nargc > ++optind)
117			optarg = nargv[optind];
118		else {
119			/* option-argument absent */
120			place = EMSG;
121			if (*ostr == ':')
122				return (BADARG);
123			if (opterr)
124				(void)fprintf(stderr,
125				    "%s: option requires an argument -- %c\n",
126				    _getprogname(), optopt);
127			return (BADCH);
128		}
129		place = EMSG;
130		++optind;
131	}
132	return (optopt);			/* return option letter */
133}
134