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