1 /*
2 * getlopt.c
3 *
4 * Oliver Fromme <olli@fromme.com>
5 *
6 * Copyright (C) 1997,1998,1999
7 * Oliver Fromme. 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 author nor the names of any co-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 OLIVER FROMME 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 OLIVER FROMME 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 * @(#)$Id: getlopt.c,v 1.3 1999/01/01 23:31:48 olli Exp $
34 */
35
36 static const char cvsid[]
37 = "@(#)$Id: getlopt.c,v 1.3 1999/01/01 23:31:48 olli Exp $";
38
39 #include <stdio.h>
40 #include "getlopt.h"
41
42 int loptind = 1; /* index in argv[] */
43 int loptchr = 0; /* index in argv[loptind] */
44 char *loptarg; /* points to argument if present, else to option */
45
46 #if defined(ultrix) || defined(ULTRIX)
47 char *
strdup(char * src)48 strdup (char *src)
49 {
50 char *dest;
51
52 if (!(dest = (char *) malloc(strlen(src) + 1)))
53 return (NULL);
54 return (strcpy(dest, src));
55 }
56 #endif
57
58 const topt *
findopt(int islong,char * opt,const topt * opts)59 findopt (int islong, char *opt, const topt *opts)
60 {
61 if (!opts)
62 return (0);
63 while (opts->lname || opts->sname) {
64 if (islong) {
65 if (opts->lname && !strcmp(opts->lname, opt))
66 return (opts);
67 }
68 else
69 if (opts->sname == *opt)
70 return (opts);
71 opts++;
72 }
73 return (0);
74 }
75
76 int
performoption(int argc,char * argv[],const topt * opt)77 performoption (int argc, char *argv[], const topt *opt)
78 {
79 int result = GLO_CONTINUE;
80
81 if (!(opt->flags & 1)) /* doesn't take argument */
82 if (opt->var)
83 if (opt->flags & 2) /* var is *char */
84 *((char *) opt->var) = (char) opt->value;
85 else
86 *((int *) opt->var) = opt->value;
87 else
88 result = opt->value ? opt->value : opt->sname;
89 else { /* requires argument */
90 if (loptind >= argc)
91 return (GLO_NOARG);
92 loptarg = argv[loptind++]+loptchr;
93 loptchr = 0;
94 if (opt->var)
95 if (opt->flags & 2) /* var is *char */
96 *((char **) opt->var) = strdup(loptarg);
97 else
98 *((int *) opt->var) = atoi(loptarg);
99 else
100 result = opt->value ? opt->value : opt->sname;
101 }
102 if (opt->func)
103 if (opt->func(loptarg) < 0)
104 result = GLO_USERERR;
105 return (result);
106 }
107
108 int
getsingleopt(int argc,char * argv[],const topt * opts)109 getsingleopt (int argc, char *argv[], const topt *opts)
110 {
111 char *thisopt;
112 const topt *opt;
113 static char shortopt[2] = {0, 0};
114
115 if (loptind >= argc)
116 return (GLO_END);
117 thisopt = argv[loptind];
118 if (!loptchr) { /* start new option string */
119 if (thisopt[0] != '-' || !thisopt[1]) /* no more options */
120 return (GLO_END);
121 if (thisopt[1] == '-') /* "--" */
122 if (thisopt[2]) { /* long option */
123 loptarg = thisopt + 2;
124 loptind++;
125 if (!(opt = findopt(1, thisopt + 2, opts)))
126 return (GLO_UNKNOWN);
127 else
128 return (performoption(argc, argv, opt));
129 }
130 else { /* "--" == end of options */
131 loptind++;
132 return (GLO_END);
133 }
134 else /* start short option(s) */
135 loptchr = 1;
136 }
137 shortopt[0] = thisopt[loptchr];
138 loptarg = shortopt;
139 opt = findopt(0, thisopt + (loptchr++), opts);
140 if (!thisopt[loptchr]) {
141 loptind++;
142 loptchr = 0;
143 }
144 if (!opt)
145 return (GLO_UNKNOWN);
146 else
147 return (performoption(argc, argv, opt));
148 }
149
150 int
getlopt(int argc,char * argv[],const topt * opts)151 getlopt (int argc, char *argv[], const topt *opts)
152 {
153 int result;
154
155 while ((result = getsingleopt(argc, argv, opts)) == GLO_CONTINUE);
156 return (result);
157 }
158
159 int
parselopts(int argc,char * argv[],const topt * opts,char * progname)160 parselopts (int argc, char *argv[], const topt *opts, char *progname)
161 {
162 int result;
163
164 while ((result = getlopt(argc, argv, opts)))
165 switch (result) {
166 case GLO_UNKNOWN:
167 fprintf (stderr, "%s: Unknown option \"%s\".\n",
168 progname, loptarg);
169 exit (1);
170 case GLO_NOARG:
171 fprintf (stderr, "%s: Missing argument for option \"%s\".\n",
172 progname, loptarg);
173 exit (1);
174 case GLO_USERERR:
175 return result;
176 }
177 return result;
178 }
179
180 /* EOF */
181