Path: blob/main/crypto/krb5/src/util/support/getopt_long.c
34889 views
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */1/*2* Copyright (c) 1987, 1993, 1994, 19963* The Regents of the University of California. All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13* 3. All advertising materials mentioning features or use of this software14* must display the following acknowledgement:15* This product includes software developed by the University of16* California, Berkeley and its contributors.17* 4. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/33#ifndef HAVE_GETOPT_LONG34#include <assert.h>35#include <errno.h>36#include <stdio.h>37#include <stdlib.h>38#include <string.h>39#include "k5-platform.h"4041#define __P(x) x42#define _DIAGASSERT(x) assert(x)4344static char * __progname __P((char *));45int getopt_internal __P((int, char * const *, const char *));4647static char *48__progname(nargv0)49char * nargv0;50{51char * tmp;5253_DIAGASSERT(nargv0 != NULL);5455tmp = strrchr(nargv0, '/');56if (tmp)57tmp++;58else59tmp = nargv0;60return(tmp);61}6263#define BADCH (int)'?'64#define BADARG (int)':'65#define EMSG ""6667/*68* getopt --69* Parse argc/argv argument vector.70*/71int72getopt_internal(nargc, nargv, ostr)73int nargc;74char * const *nargv;75const char *ostr;76{77static char *place = EMSG; /* option letter processing */78char *oli; /* option letter list index */7980_DIAGASSERT(nargv != NULL);81_DIAGASSERT(ostr != NULL);8283if (!*place) { /* update scanning pointer */84if (optind >= nargc || *(place = nargv[optind]) != '-') {85place = EMSG;86return (-1);87}88if (place[1] && *++place == '-') { /* found "--" */89/* ++optind; */90place = EMSG;91return (-2);92}93} /* option letter okay? */94if ((optopt = (int)*place++) == (int)':' ||95!(oli = strchr(ostr, optopt))) {96/*97* if the user didn't specify '-' as an option,98* assume it means -1.99*/100if (optopt == (int)'-')101return (-1);102if (!*place)103++optind;104if (opterr && *ostr != ':')105(void)fprintf(stderr,106"%s: illegal option -- %c\n", __progname(nargv[0]), optopt);107return (BADCH);108}109if (*++oli != ':') { /* don't need argument */110optarg = NULL;111if (!*place)112++optind;113} else { /* need an argument */114if (*place) /* no white space */115optarg = place;116else if (nargc <= ++optind) { /* no arg */117place = EMSG;118if ((opterr) && (*ostr != ':'))119(void)fprintf(stderr,120"%s: option requires an argument -- %c\n",121__progname(nargv[0]), optopt);122return (BADARG);123} else /* white space */124optarg = nargv[optind];125place = EMSG;126++optind;127}128return (optopt); /* dump back option letter */129}130131#if 0132/*133* getopt --134* Parse argc/argv argument vector.135*/136int137getopt2(nargc, nargv, ostr)138int nargc;139char * const *nargv;140const char *ostr;141{142int retval;143144if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {145retval = -1;146++optind;147}148return(retval);149}150#endif151152/*153* getopt_long --154* Parse argc/argv argument vector.155*/156int157getopt_long(nargc, nargv, options, long_options, index)158int nargc;159char ** nargv;160char * options;161struct option * long_options;162int * index;163{164int retval;165166_DIAGASSERT(nargv != NULL);167_DIAGASSERT(options != NULL);168_DIAGASSERT(long_options != NULL);169/* index may be NULL */170171if ((retval = getopt_internal(nargc, nargv, options)) == -2) {172char *current_argv = nargv[optind++] + 2, *has_equal;173int i, current_argv_len, match = -1;174175if (*current_argv == '\0') {176return(-1);177}178if ((has_equal = strchr(current_argv, '=')) != NULL) {179current_argv_len = has_equal - current_argv;180has_equal++;181} else182current_argv_len = strlen(current_argv);183184for (i = 0; long_options[i].name; i++) {185if (strncmp(current_argv, long_options[i].name, current_argv_len))186continue;187188if (strlen(long_options[i].name) == (unsigned)current_argv_len) {189match = i;190break;191}192if (match == -1)193match = i;194}195if (match != -1) {196if (long_options[match].has_arg == required_argument ||197long_options[match].has_arg == optional_argument) {198if (has_equal)199optarg = has_equal;200else201optarg = nargv[optind++];202}203if ((long_options[match].has_arg == required_argument)204&& (optarg == NULL)) {205/*206* Missing argument, leading :207* indicates no error should be generated208*/209if ((opterr) && (*options != ':'))210(void)fprintf(stderr,211"%s: option requires an argument -- %s\n",212__progname(nargv[0]), current_argv);213return (BADARG);214}215} else { /* No matching argument */216if ((opterr) && (*options != ':'))217(void)fprintf(stderr,218"%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);219return (BADCH);220}221if (long_options[match].flag) {222*long_options[match].flag = long_options[match].val;223retval = 0;224} else225retval = long_options[match].val;226if (index)227*index = match;228}229return(retval);230}231#endif /* not HAVE_GETOPT_LONG */232233234