/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1992-1996,2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* This file contains getoptstr(), which is getopt() for strings of arguments
* (not arrays of strings). It is used by the bootloader ({*fs,inet}boot) and
* the kernel to process argument strings.
*/
#include "getoptstr.h"
#include <sys/null.h>
/*
* This routine needs to be supplied by whatever uses this file.
*/
char *strchr(const char *s, int c);
#define ISNTWORDCH(c) ((c) == '\0' || ISSPACE(c))
/*
* Prepare a gos_params structure for use by getoptstr().
*/
void
getoptstr_init(struct gos_params *params)
{
params->gos_pos = 1;
}
/*
* Modeled after lib/libc/port/gen/getopt.c.
*
* With params->gos_opts set to a string of options and params->gos_strp set to
* an argument string, getoptstr returns
* * the next option letter, where the options are given by the
* params->gos_opts string. If the option is followed by a ':' in gos_opts,
* then params->gos_optargp will point to the beginning of the argument in
* the string, and params->gos_optarglen will contain its length.
* * -1 if "--" or a non-option argument is encountered. In the former
* case, params->gos_strp is advanced to the next argument.
* * '?' if an illegal option is encountered or if an argument is not
* supplied for an option which requires one and ':' is not the first
* character of opts. In both cases, the option letter is available in
* params->gos_last_opt, and in the former case, params->gos_errp will
* point to the offending character.
* * ':' if an argument is not supplied for an option which requires one and
* ':' is the first character of params->gos_opts.
*/
int
getoptstr(struct gos_params *params)
{
char c;
char *cp;
/*
* const because we should update params. Just make sure you don't
* use this after you update params->gos_strp.
*/
const char * const strp = params->gos_strp;
if (params->gos_opts == NULL || strp == NULL)
return (-1);
if (params->gos_pos == 1) {
/* At beginning of new word. */
if (strp[0] == '\0' || strp[0] != '-')
return (-1);
if (ISNTWORDCH(strp[1])) {
/* Lone dash. */
return (-1);
}
/* Check for "--" */
if (strp[1] == '-' && ISNTWORDCH(strp[2])) {
params->gos_strp = &strp[2];
SKIP_SPC(params->gos_strp);
return (-1);
}
}
params->gos_last_opt = c = strp[params->gos_pos];
if (c == ':' || (cp = strchr(params->gos_opts, c)) == NULL) {
/* Unrecognized option error. */
params->gos_errp = &strp[params->gos_pos];
++params->gos_pos;
if (ISNTWORDCH(strp[params->gos_pos])) {
params->gos_strp = &strp[params->gos_pos];
SKIP_SPC(params->gos_strp);
params->gos_pos = 1;
}
return ('?');
}
if (cp[1] == ':') {
/* This option expects an argument. */
params->gos_strp = &strp[params->gos_pos + 1];
if (ISNTWORDCH(*params->gos_strp)) {
/* The argument is in the next word. */
SKIP_SPC(params->gos_strp);
if (*params->gos_strp == '\0') {
/* Not. Missing argument. */
params->gos_pos = 1;
params->gos_optargp = NULL;
return (params->gos_opts[0] == ':' ? ':' : '?');
}
}
params->gos_optargp = params->gos_strp;
/* Advance to the next word. */
SKIP_WORD(params->gos_strp);
params->gos_optarglen = params->gos_strp - params->gos_optargp;
SKIP_SPC(params->gos_strp);
params->gos_pos = 1;
} else {
++params->gos_pos;
if (ISNTWORDCH(strp[params->gos_pos])) {
params->gos_strp = &strp[params->gos_pos];
SKIP_SPC(params->gos_strp);
params->gos_pos = 1;
}
params->gos_optargp = NULL;
}
return (c);
}