1296637Ssjg/*	$NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $	*/
2296637Ssjg
3236769Sobrien/*
4236769Sobrien * Copyright (c) 1987, 1993, 1994
5236769Sobrien *	The Regents of the University of California.  All rights reserved.
6236769Sobrien *
7236769Sobrien * Redistribution and use in source and binary forms, with or without
8236769Sobrien * modification, are permitted provided that the following conditions
9236769Sobrien * are met:
10236769Sobrien * 1. Redistributions of source code must retain the above copyright
11236769Sobrien *    notice, this list of conditions and the following disclaimer.
12236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright
13236769Sobrien *    notice, this list of conditions and the following disclaimer in the
14236769Sobrien *    documentation and/or other materials provided with the distribution.
15296637Ssjg * 3. Neither the name of the University nor the names of its contributors
16236769Sobrien *    may be used to endorse or promote products derived from this software
17236769Sobrien *    without specific prior written permission.
18236769Sobrien *
19236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22236769Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29236769Sobrien * SUCH DAMAGE.
30236769Sobrien */
31236769Sobrien
32236769Sobrien#ifdef HAVE_CONFIG_H
33236769Sobrien# include "config.h"
34236769Sobrien#endif
35236769Sobrien#if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT)
36296637Ssjg#include <sys/cdefs.h>
37236769Sobrien
38236769Sobrien#include <stdio.h>
39236769Sobrien#include <stdlib.h>
40236769Sobrien#include <string.h>
41236769Sobrien
42236769Sobrien
43236769Sobrien#define	BADCH	(int)'?'
44236769Sobrien#define	BADARG	(int)':'
45236769Sobrien#define	EMSG	""
46236769Sobrien
47236769Sobrienint	opterr = 1,		/* if error message should be printed */
48236769Sobrien	optind = 1,		/* index into parent argv vector */
49236769Sobrien	optopt = BADCH,		/* character checked for validity */
50236769Sobrien	optreset;		/* reset getopt */
51236769Sobrienchar	*optarg;		/* argument associated with option */
52236769Sobrien
53236769Sobrien/*
54236769Sobrien * getopt --
55236769Sobrien *	Parse argc/argv argument vector.
56236769Sobrien */
57236769Sobrienint
58296637Ssjggetopt(int nargc, char * const nargv[], const char *ostr)
59236769Sobrien{
60236769Sobrien	extern char *__progname;
61296637Ssjg	static const char *place = EMSG; 	/* option letter processing */
62236769Sobrien	char *oli;				/* option letter list index */
63236769Sobrien
64236769Sobrien#ifndef BSD4_4
65236769Sobrien	if (!__progname) {
66236769Sobrien		if (__progname = strrchr(nargv[0], '/'))
67236769Sobrien			++__progname;
68236769Sobrien		else
69236769Sobrien			__progname = nargv[0];
70236769Sobrien	}
71236769Sobrien#endif
72236769Sobrien
73296637Ssjg	if (optreset || *place == 0) {		/* update scanning pointer */
74236769Sobrien		optreset = 0;
75296637Ssjg		place = nargv[optind];
76296637Ssjg		if (optind >= nargc || *place++ != '-') {
77296637Ssjg			/* Argument is absent or is not an option */
78236769Sobrien			place = EMSG;
79236769Sobrien			return (-1);
80236769Sobrien		}
81296637Ssjg		optopt = *place++;
82296637Ssjg		if (optopt == '-' && *place == 0) {
83296637Ssjg			/* "--" => end of options */
84236769Sobrien			++optind;
85236769Sobrien			place = EMSG;
86236769Sobrien			return (-1);
87236769Sobrien		}
88296637Ssjg		if (optopt == 0) {
89296637Ssjg			/* Solitary '-', treat as a '-' option
90296637Ssjg			   if the program (eg su) is looking for it. */
91296637Ssjg			place = EMSG;
92296637Ssjg			if (strchr(ostr, '-') == NULL)
93296637Ssjg				return -1;
94296637Ssjg			optopt = '-';
95296637Ssjg		}
96296637Ssjg	} else
97296637Ssjg		optopt = *place++;
98296637Ssjg
99296637Ssjg	/* See if option letter is one the caller wanted... */
100296637Ssjg	if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
101296637Ssjg		if (*place == 0)
102236769Sobrien			++optind;
103236769Sobrien		if (opterr && *ostr != ':')
104236769Sobrien			(void)fprintf(stderr,
105296637Ssjg			    "%s: unknown option -- %c\n", __progname, optopt);
106236769Sobrien		return (BADCH);
107236769Sobrien	}
108296637Ssjg
109296637Ssjg	/* Does this option need an argument? */
110296637Ssjg	if (oli[1] != ':') {
111296637Ssjg		/* don't need argument */
112236769Sobrien		optarg = NULL;
113296637Ssjg		if (*place == 0)
114236769Sobrien			++optind;
115296637Ssjg	} else {
116296637Ssjg		/* Option-argument is either the rest of this argument or the
117296637Ssjg		   entire next argument. */
118296637Ssjg		if (*place)
119296637Ssjg			optarg = __UNCONST(place);
120296637Ssjg		else if (oli[2] == ':')
121296637Ssjg			/*
122296637Ssjg			 * GNU Extension, for optional arguments if the rest of
123296637Ssjg			 * the argument is empty, we return NULL
124296637Ssjg			 */
125296637Ssjg			optarg = NULL;
126296637Ssjg		else if (nargc > ++optind)
127296637Ssjg			optarg = nargv[optind];
128296637Ssjg		else {
129296637Ssjg			/* option-argument absent */
130236769Sobrien			place = EMSG;
131236769Sobrien			if (*ostr == ':')
132236769Sobrien				return (BADARG);
133236769Sobrien			if (opterr)
134236769Sobrien				(void)fprintf(stderr,
135236769Sobrien				    "%s: option requires an argument -- %c\n",
136236769Sobrien				    __progname, optopt);
137236769Sobrien			return (BADCH);
138236769Sobrien		}
139236769Sobrien		place = EMSG;
140236769Sobrien		++optind;
141236769Sobrien	}
142296637Ssjg	return (optopt);			/* return option letter */
143236769Sobrien}
144236769Sobrien#endif
145236769Sobrien#ifdef MAIN
146236769Sobrien#ifndef BSD4_4
147236769Sobrienchar *__progname;
148236769Sobrien#endif
149236769Sobrien
150236769Sobrienint
151236769Sobrienmain(argc, argv)
152236769Sobrien	int argc;
153236769Sobrien	char *argv[];
154236769Sobrien{
155236769Sobrien	int c;
156236769Sobrien	char *opts = argv[1];
157236769Sobrien
158236769Sobrien	--argc;
159236769Sobrien	++argv;
160236769Sobrien
161236769Sobrien	while ((c = getopt(argc, argv, opts)) != EOF) {
162236769Sobrien		switch (c) {
163236769Sobrien		case '-':
164236769Sobrien			if (optarg)
165236769Sobrien				printf("--%s ", optarg);
166236769Sobrien			break;
167236769Sobrien		case '?':
168236769Sobrien			exit(1);
169236769Sobrien			break;
170236769Sobrien		default:
171236769Sobrien			if (optarg)
172236769Sobrien				printf("-%c %s ", c, optarg);
173236769Sobrien			else
174236769Sobrien				printf("-%c ", c);
175236769Sobrien			break;
176236769Sobrien		}
177236769Sobrien	}
178236769Sobrien
179236769Sobrien	if (optind < argc) {
180236769Sobrien		printf("-- ");
181236769Sobrien		for (; optind < argc; ++optind) {
182236769Sobrien			printf("%s ", argv[optind]);
183236769Sobrien		}
184236769Sobrien	}
185236769Sobrien	printf("\n");
186236769Sobrien	exit(0);
187236769Sobrien}
188236769Sobrien#endif
189