idmap_engine.c revision c5c4113dfcabb1eed3d4bdf7609de5170027a794
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <locale.h>
#include <ctype.h>
#ifdef WITH_LIBTECLA
#include <libtecla.h>
#endif
#include "idmap_engine.h"
/* The maximal line length. Longer lines may not be parsed OK. */
#define MAX_CMD_LINE_SZ 1023
#ifdef WITH_LIBTECLA
#define MAX_HISTORY_LINES 1023
/* LINTED E_STATIC_UNUSED */
#endif
/* Array for arguments of the actuall command */
static char ** my_argv;
/* Allocated size for my_argv */
static int my_argv_size = 16;
/* Actuall length of my_argv */
static int my_argc;
/* Array for subcommands */
/* my_comc length */
static int my_comc;
/* Input filename specified by the -f flag */
static char *my_filename;
/*
* Batch mode means reading file, stdin or libtecla input. Shell input is
* a non-batch mode.
*/
static int my_batch_mode;
/* Array of all possible flags */
/* getopt variables */
extern char *optarg;
/* Fill the flags array: */
static int
{
char c;
optind = 1;
switch (c) {
case '?':
return (-1);
case ':':
/* This is relevant only if options starts with ':': */
gettext("Option %s: missing parameter\n"),
return (-1);
default:
else
}
}
return (optind);
}
/* Unset all flags */
static void
{
}
/* determine which subcommand is argv[0] and execute its handler */
static int
int i;
if (argc == 0) {
if (my_batch_mode)
return (0);
return (-1);
}
for (i = 0; i < my_comc; i++) {
int optind;
int rc;
continue;
/* We found it. Now execute the handler. */
if (optind < 0) {
return (-1);
}
return (rc);
}
argv[0]);
return (-1);
}
/*
* Read another parameter from "from", up to a space char (unless it
* is quoted). Duplicate it to "to". Remove quotation, if any.
*/
static int
char c;
int last_slash = 0; /* Preceded by a slash? */
int in_string = 0; /* Inside quites? */
int is_param = 0;
from_i = 0;
from_i++;
buf_size *= 2;
}
if (c == '"' && !last_slash) {
is_param = 1;
continue;
} else if (c == '\\' && !last_slash) {
last_slash = 1;
continue;
break;
}
last_slash = 0;
}
return (0);
}
if (in_string)
return (-1);
return (from_i);
}
/*
* Split a string to a parameter array and append it to the specified position
* of the array
*/
static int
line2array(const char *line)
{
const char *cur;
char *param;
int len;
if (my_argc > my_argv_size) {
my_argv_size *= 2;
my_argv_size * sizeof (char *));
}
++my_argc;
/* quotation not closed */
if (len < 0)
return (-1);
}
return (0);
}
/* Clean all aruments from my_argv. Don't deallocate my_argv itself. */
static void
{
int i;
for (i = 0; i < my_argc; i++) {
}
my_argc = 0;
}
#ifdef WITH_LIBTECLA
/* This is libtecla tab completion. */
static
{
/*
* WordCompletion *cpl; const char *line; int word_end are
* passed from the CPL_MATCH_FN macro.
*/
int i;
char *prefix;
int prefix_l;
/* We go on even if quotation is not closed */
(void) line2array(line);
/* Beginning of the line: */
if (my_argc == 0) {
for (i = 0; i < my_comc; i++)
goto cleanup;
}
/* Is there something to complete? */
goto cleanup;
/* Subcommand name: */
if (my_argc == 1) {
for (i = 0; i < my_comc; i++)
"", " ");
goto cleanup;
}
/* Long options: */
char *paren;
char *thesis;
int i;
for (i = 0; i < my_comc; i++)
break;
}
/* No such subcommand, or not enough memory: */
goto cleanup;
/* Short option or thesis must precede, so this is safe: */
*paren = '-';
*thesis = '\0';
}
}
/* "--" is a valid completion */
if (prefix_l == 2) {
word_end - 2,
}
}
return (0);
}
/* libtecla subshell: */
static int
{
int rc = 0;
char *prompt;
const char *line;
gettext("Error reading terminal: %s.\n"),
return (-1);
}
for (;;) {
prompt = "> ";
switch (gl_return_status(gl_h)) {
case GLR_SIGNAL:
goto new_line;
case GLR_EOF:
(void) line2array("exit");
break;
case GLR_ERROR:
gettext("Error reading terminal: %s.\n"),
rc = -1;
goto end_of_input;
default:
exit(1);
}
} else {
if (line2array(line) < 0) {
gettext("Quotation not closed\n"));
goto new_line;
}
if (my_argc == 0) {
goto new_line;
}
my_argc--;
goto continue_line;
}
}
break;
}
}
return (rc);
}
#endif
/* Interpretation of a source file given by "name" */
static int
source_interp(const char *name)
{
FILE *f;
int is_stdin;
int rc = -1;
char line[MAX_CMD_LINE_SZ];
f = stdin;
is_stdin = 1;
} else {
is_stdin = 0;
if (f == NULL) {
return (-1);
}
}
if (line2array(line) < 0) {
gettext("Quotation not closed\n"));
continue;
}
/* We do not wan't "\n" as the last parameter */
my_argc--;
continue;
}
rc = 0;
break;
}
}
if (my_argc > 0) {
rc = 1;
}
if (!is_stdin)
(void) fclose(f);
return (rc);
}
/*
* Initialize the engine.
* comc, comv is the array of subcommands and its length,
* argc, argv are arguments to main to be scanned for -f filename and
* the length og the array,
* is_batch_mode passes to the caller the information if the
* batch mode is on.
*
* Return values:
* 0: ... OK
* IDMAP_ENG_ERROR: error and message printed already
* IDMAP_ENG_ERROR_SILENT: error and message needs to be printed
*
*/
int
int *is_batch_mode) {
int c;
my_argc = 0;
if (argc < 1) {
my_filename = NULL;
#ifdef WITH_LIBTECLA
my_batch_mode = 1;
#else
my_batch_mode = 0;
return (IDMAP_ENG_ERROR_SILENT);
#endif
} else
my_batch_mode = 1;
goto the_end;
}
my_batch_mode = 0;
optind = 0;
"f:(command-file)")) != EOF) {
switch (c) {
case '?':
return (IDMAP_ENG_ERROR);
case 'f':
my_batch_mode = 1;
break;
default:
exit(1);
}
}
if (is_batch_mode != NULL)
return (0);
}
/* finitialize the engine */
int
engine_fini() {
return (0);
}
/*
* Interpret the subcommands defined by the arguments, unless
* my_batch_mode was set on in egnine_init.
*/
int
{
int rc = -1;
if (my_batch_mode) {
#ifdef WITH_LIBTECLA
rc = interactive_interp();
else
#endif
goto cleanup;
}
return (rc);
}