1*f77396c9Srin /* $NetBSD: getopt.c,v 1.2 2024/06/29 07:56:56 rin Exp $ */
230d0c2dbSrin
330d0c2dbSrin /*
430d0c2dbSrin * Copyright (c) 1987, 1993, 1994
530d0c2dbSrin * The Regents of the University of California. All rights reserved.
630d0c2dbSrin *
730d0c2dbSrin * Redistribution and use in source and binary forms, with or without
830d0c2dbSrin * modification, are permitted provided that the following conditions
930d0c2dbSrin * are met:
1030d0c2dbSrin * 1. Redistributions of source code must retain the above copyright
1130d0c2dbSrin * notice, this list of conditions and the following disclaimer.
1230d0c2dbSrin * 2. Redistributions in binary form must reproduce the above copyright
1330d0c2dbSrin * notice, this list of conditions and the following disclaimer in the
1430d0c2dbSrin * documentation and/or other materials provided with the distribution.
1530d0c2dbSrin * 3. Neither the name of the University nor the names of its contributors
1630d0c2dbSrin * may be used to endorse or promote products derived from this software
1730d0c2dbSrin * without specific prior written permission.
1830d0c2dbSrin *
1930d0c2dbSrin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2030d0c2dbSrin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2130d0c2dbSrin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2230d0c2dbSrin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2330d0c2dbSrin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2430d0c2dbSrin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2530d0c2dbSrin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2630d0c2dbSrin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2730d0c2dbSrin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2830d0c2dbSrin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2930d0c2dbSrin * SUCH DAMAGE.
3030d0c2dbSrin */
3130d0c2dbSrin
3230d0c2dbSrin #include <sys/cdefs.h>
33*f77396c9Srin __RCSID("$NetBSD: getopt.c,v 1.2 2024/06/29 07:56:56 rin Exp $");
34*f77396c9Srin
35*f77396c9Srin #if defined(_KERNEL) || defined(_STANDALONE)
36*f77396c9Srin
37*f77396c9Srin #include <lib/libsa/stand.h>
38*f77396c9Srin #include <lib/libkern/libkern.h>
39*f77396c9Srin
40*f77396c9Srin #define EPRINTF(fmt, args...) printf(fmt, ##args)
41*f77396c9Srin
42*f77396c9Srin #else
4330d0c2dbSrin
4430d0c2dbSrin #include "namespace.h"
4530d0c2dbSrin
4630d0c2dbSrin #include <assert.h>
4730d0c2dbSrin #include <errno.h>
4830d0c2dbSrin #include <stdio.h>
4930d0c2dbSrin #include <stdlib.h>
5030d0c2dbSrin #include <string.h>
5130d0c2dbSrin #include <unistd.h>
5230d0c2dbSrin
5330d0c2dbSrin #ifdef __weak_alias
5430d0c2dbSrin __weak_alias(getopt,_getopt)
5530d0c2dbSrin #endif
5630d0c2dbSrin
57*f77396c9Srin #define EPRINTF(fmt, args...) \
58*f77396c9Srin fprintf(stderr, "%s: " fmt, getprogname(), ##args)
59*f77396c9Srin
60*f77396c9Srin #endif /* !_KERNEL && !_STANDALONE */
61*f77396c9Srin
6230d0c2dbSrin int opterr = 1, /* if error message should be printed */
6330d0c2dbSrin optind = 1, /* index into parent argv vector */
6430d0c2dbSrin optopt, /* character checked for validity */
6530d0c2dbSrin optreset; /* reset getopt */
6630d0c2dbSrin char *optarg; /* argument associated with option */
6730d0c2dbSrin
6830d0c2dbSrin #define BADCH (int)'?'
6930d0c2dbSrin #define BADARG (int)':'
7030d0c2dbSrin #define EMSG ""
7130d0c2dbSrin
7230d0c2dbSrin /*
7330d0c2dbSrin * getopt --
7430d0c2dbSrin * Parse argc/argv argument vector.
7530d0c2dbSrin */
7630d0c2dbSrin int
getopt(int nargc,char * const nargv[],const char * ostr)7730d0c2dbSrin getopt(int nargc, char * const nargv[], const char *ostr)
7830d0c2dbSrin {
7930d0c2dbSrin static const char *place = EMSG; /* option letter processing */
8030d0c2dbSrin const char *oli; /* option letter list index */
8130d0c2dbSrin
8230d0c2dbSrin _DIAGASSERT(nargv != NULL);
8330d0c2dbSrin _DIAGASSERT(ostr != NULL);
8430d0c2dbSrin
8530d0c2dbSrin if (optreset || *place == 0) { /* update scanning pointer */
8630d0c2dbSrin optreset = 0;
8730d0c2dbSrin place = nargv[optind];
8830d0c2dbSrin if (optind >= nargc || *place++ != '-') {
8930d0c2dbSrin /* Argument is absent or is not an option */
9030d0c2dbSrin place = EMSG;
9130d0c2dbSrin return (-1);
9230d0c2dbSrin }
9330d0c2dbSrin optopt = *place++;
9430d0c2dbSrin if (optopt == '-' && *place == 0) {
9530d0c2dbSrin /* "--" => end of options */
9630d0c2dbSrin ++optind;
9730d0c2dbSrin place = EMSG;
9830d0c2dbSrin return (-1);
9930d0c2dbSrin }
10030d0c2dbSrin if (optopt == 0) {
10130d0c2dbSrin /* Solitary '-', treat as a '-' option
10230d0c2dbSrin if the program (eg su) is looking for it. */
10330d0c2dbSrin place = EMSG;
10430d0c2dbSrin if (strchr(ostr, '-') == NULL)
10530d0c2dbSrin return -1;
10630d0c2dbSrin optopt = '-';
10730d0c2dbSrin }
10830d0c2dbSrin } else
10930d0c2dbSrin optopt = *place++;
11030d0c2dbSrin
11130d0c2dbSrin /* See if option letter is one the caller wanted... */
11230d0c2dbSrin if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
11330d0c2dbSrin if (*place == 0)
11430d0c2dbSrin ++optind;
11530d0c2dbSrin if (opterr && *ostr != ':')
116*f77396c9Srin (void)EPRINTF("unknown option -- %c\n", optopt);
11730d0c2dbSrin return (BADCH);
11830d0c2dbSrin }
11930d0c2dbSrin
12030d0c2dbSrin /* Does this option need an argument? */
12130d0c2dbSrin if (oli[1] != ':') {
12230d0c2dbSrin /* don't need argument */
12330d0c2dbSrin optarg = NULL;
12430d0c2dbSrin if (*place == 0)
12530d0c2dbSrin ++optind;
12630d0c2dbSrin } else {
12730d0c2dbSrin /* Option-argument is either the rest of this argument or the
12830d0c2dbSrin entire next argument. */
12930d0c2dbSrin if (*place)
13030d0c2dbSrin optarg = __UNCONST(place);
13130d0c2dbSrin else if (oli[2] == ':')
13230d0c2dbSrin /*
13330d0c2dbSrin * GNU Extension, for optional arguments if the rest of
13430d0c2dbSrin * the argument is empty, we return NULL
13530d0c2dbSrin */
13630d0c2dbSrin optarg = NULL;
13730d0c2dbSrin else if (nargc > ++optind)
13830d0c2dbSrin optarg = nargv[optind];
13930d0c2dbSrin else {
14030d0c2dbSrin /* option-argument absent */
14130d0c2dbSrin place = EMSG;
14230d0c2dbSrin if (*ostr == ':')
14330d0c2dbSrin return (BADARG);
14430d0c2dbSrin if (opterr)
145*f77396c9Srin (void)EPRINTF(
146*f77396c9Srin "option requires an argument -- %c\n",
147*f77396c9Srin optopt);
14830d0c2dbSrin return (BADCH);
14930d0c2dbSrin }
15030d0c2dbSrin place = EMSG;
15130d0c2dbSrin ++optind;
15230d0c2dbSrin }
15330d0c2dbSrin return (optopt); /* return option letter */
15430d0c2dbSrin }
155