1c5c4113dSnw141292 /*
2c5c4113dSnw141292 * CDDL HEADER START
3c5c4113dSnw141292 *
4c5c4113dSnw141292 * The contents of this file are subject to the terms of the
5c5c4113dSnw141292 * Common Development and Distribution License (the "License").
6c5c4113dSnw141292 * You may not use this file except in compliance with the License.
7c5c4113dSnw141292 *
8c5c4113dSnw141292 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c5c4113dSnw141292 * or http://www.opensolaris.org/os/licensing.
10c5c4113dSnw141292 * See the License for the specific language governing permissions
11c5c4113dSnw141292 * and limitations under the License.
12c5c4113dSnw141292 *
13c5c4113dSnw141292 * When distributing Covered Code, include this CDDL HEADER in each
14c5c4113dSnw141292 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c5c4113dSnw141292 * If applicable, add the following below this CDDL HEADER, with the
16c5c4113dSnw141292 * fields enclosed by brackets "[]" replaced with your own identifying
17c5c4113dSnw141292 * information: Portions Copyright [yyyy] [name of copyright owner]
18c5c4113dSnw141292 *
19c5c4113dSnw141292 * CDDL HEADER END
20c5c4113dSnw141292 */
21c5c4113dSnw141292 /*
224edd44c5Sjp151216 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23c5c4113dSnw141292 * Use is subject to license terms.
24c5c4113dSnw141292 */
25c5c4113dSnw141292
26c5c4113dSnw141292 #pragma ident "%Z%%M% %I% %E% SMI"
27c5c4113dSnw141292
28c5c4113dSnw141292
29c5c4113dSnw141292
30c5c4113dSnw141292 #include <stdio.h>
31c5c4113dSnw141292 #include <stdlib.h>
32c5c4113dSnw141292 #include <strings.h>
33c5c4113dSnw141292 #include <locale.h>
34c5c4113dSnw141292 #include <ctype.h>
35c5c4113dSnw141292 #ifdef WITH_LIBTECLA
36c5c4113dSnw141292 #include <libtecla.h>
37c5c4113dSnw141292 #endif
38c5c4113dSnw141292 #include "idmap_engine.h"
39c5c4113dSnw141292
40c5c4113dSnw141292 /* The maximal line length. Longer lines may not be parsed OK. */
41c5c4113dSnw141292 #define MAX_CMD_LINE_SZ 1023
42c5c4113dSnw141292
43c5c4113dSnw141292 #ifdef WITH_LIBTECLA
44c5c4113dSnw141292 #define MAX_HISTORY_LINES 1023
45c5c4113dSnw141292 static GetLine * gl_h;
46c5c4113dSnw141292 /* LINTED E_STATIC_UNUSED */
47c5c4113dSnw141292 #endif
48c5c4113dSnw141292
49c5c4113dSnw141292 /* Array for arguments of the actuall command */
50c5c4113dSnw141292 static char ** my_argv;
51c5c4113dSnw141292 /* Allocated size for my_argv */
52c5c4113dSnw141292 static int my_argv_size = 16;
53c5c4113dSnw141292 /* Actuall length of my_argv */
54c5c4113dSnw141292 static int my_argc;
55c5c4113dSnw141292
56c5c4113dSnw141292 /* Array for subcommands */
57c5c4113dSnw141292 static cmd_ops_t *my_comv;
58c5c4113dSnw141292 /* my_comc length */
59c5c4113dSnw141292 static int my_comc;
60c5c4113dSnw141292
61c5c4113dSnw141292 /* Input filename specified by the -f flag */
62c5c4113dSnw141292 static char *my_filename;
63c5c4113dSnw141292
64c5c4113dSnw141292 /*
65c5c4113dSnw141292 * Batch mode means reading file, stdin or libtecla input. Shell input is
66c5c4113dSnw141292 * a non-batch mode.
67c5c4113dSnw141292 */
68c5c4113dSnw141292 static int my_batch_mode;
69c5c4113dSnw141292
70c5c4113dSnw141292 /* Array of all possible flags */
71c5c4113dSnw141292 static flag_t flags[FLAG_ALPHABET_SIZE];
72c5c4113dSnw141292
73c5c4113dSnw141292 /* getopt variables */
74c5c4113dSnw141292 extern char *optarg;
75c5c4113dSnw141292 extern int optind, optopt, opterr;
76c5c4113dSnw141292
77c5c4113dSnw141292 /* Fill the flags array: */
78c5c4113dSnw141292 static int
options_parse(int argc,char * argv[],const char * options)79c5c4113dSnw141292 options_parse(int argc, char *argv[], const char *options)
80c5c4113dSnw141292 {
81c5c4113dSnw141292 char c;
82c5c4113dSnw141292
83c5c4113dSnw141292 optind = 1;
84c5c4113dSnw141292
85c5c4113dSnw141292 while ((c = getopt(argc, argv, options)) != EOF) {
86c5c4113dSnw141292 switch (c) {
87c5c4113dSnw141292 case '?':
88c5c4113dSnw141292 return (-1);
89c5c4113dSnw141292 case ':':
90c5c4113dSnw141292 /* This is relevant only if options starts with ':': */
91c5c4113dSnw141292 (void) fprintf(stderr,
92c5c4113dSnw141292 gettext("Option %s: missing parameter\n"),
93c5c4113dSnw141292 argv[optind - 1]);
94c5c4113dSnw141292 return (-1);
95c5c4113dSnw141292 default:
96c5c4113dSnw141292 if (optarg == NULL)
97c5c4113dSnw141292 flags[c] = FLAG_SET;
98c5c4113dSnw141292 else
99c5c4113dSnw141292 flags[c] = optarg;
100c5c4113dSnw141292
101c5c4113dSnw141292 }
102c5c4113dSnw141292 }
103c5c4113dSnw141292 return (optind);
104c5c4113dSnw141292 }
105c5c4113dSnw141292
106c5c4113dSnw141292 /* Unset all flags */
107c5c4113dSnw141292 static void
options_clean()108c5c4113dSnw141292 options_clean()
109c5c4113dSnw141292 {
110c5c4113dSnw141292 (void) memset(flags, 0, FLAG_ALPHABET_SIZE * sizeof (flag_t));
111c5c4113dSnw141292 }
112c5c4113dSnw141292
113c5c4113dSnw141292 /* determine which subcommand is argv[0] and execute its handler */
114c5c4113dSnw141292 static int
run_command(int argc,char ** argv,cmd_pos_t * pos)1154edd44c5Sjp151216 run_command(int argc, char **argv, cmd_pos_t *pos)
1164edd44c5Sjp151216 {
117c5c4113dSnw141292 int i;
118c5c4113dSnw141292
119c5c4113dSnw141292 if (argc == 0) {
120c5c4113dSnw141292 if (my_batch_mode)
121c5c4113dSnw141292 return (0);
122c5c4113dSnw141292 return (-1);
123c5c4113dSnw141292 }
124c5c4113dSnw141292 for (i = 0; i < my_comc; i++) {
125c5c4113dSnw141292 int optind;
126c5c4113dSnw141292 int rc;
127c5c4113dSnw141292
128c5c4113dSnw141292 if (strcmp(my_comv[i].cmd, argv[0]) != 0)
129c5c4113dSnw141292 continue;
130c5c4113dSnw141292
131c5c4113dSnw141292 /* We found it. Now execute the handler. */
132c5c4113dSnw141292 options_clean();
133c5c4113dSnw141292 optind = options_parse(argc, argv, my_comv[i].options);
134c5c4113dSnw141292 if (optind < 0) {
135c5c4113dSnw141292 return (-1);
136c5c4113dSnw141292 }
137c5c4113dSnw141292
1388e228215Sdm199847 rc = my_comv[i].p_do_func(flags,
1398e228215Sdm199847 argc - optind,
1408e228215Sdm199847 argv + optind,
1418e228215Sdm199847 pos);
142c5c4113dSnw141292
143c5c4113dSnw141292 return (rc);
144c5c4113dSnw141292 }
145c5c4113dSnw141292
146c5c4113dSnw141292 (void) fprintf(stderr, gettext("Unknown command %s\n"),
147c5c4113dSnw141292 argv[0]);
148c5c4113dSnw141292
149c5c4113dSnw141292 return (-1);
150c5c4113dSnw141292
151c5c4113dSnw141292 }
152c5c4113dSnw141292
153c5c4113dSnw141292 /*
154c5c4113dSnw141292 * Read another parameter from "from", up to a space char (unless it
155c5c4113dSnw141292 * is quoted). Duplicate it to "to". Remove quotation, if any.
156c5c4113dSnw141292 */
157c5c4113dSnw141292 static int
get_param(char ** to,const char * from)1584edd44c5Sjp151216 get_param(char **to, const char *from)
1594edd44c5Sjp151216 {
160c5c4113dSnw141292 int to_i, from_i;
161c5c4113dSnw141292 char c;
162c5c4113dSnw141292 int last_slash = 0; /* Preceded by a slash? */
163c5c4113dSnw141292 int in_string = 0; /* Inside quites? */
164c5c4113dSnw141292 int is_param = 0;
165c5c4113dSnw141292 size_t buf_size = 20; /* initial length of the buffer. */
166c5c4113dSnw141292 char *buf = (char *)malloc(buf_size * sizeof (char));
167c5c4113dSnw141292
168c5c4113dSnw141292 from_i = 0;
169c5c4113dSnw141292 while (isspace(from[from_i]))
170c5c4113dSnw141292 from_i++;
171c5c4113dSnw141292
172c5c4113dSnw141292 for (to_i = 0; '\0' != from[from_i]; from_i++) {
173c5c4113dSnw141292 c = from[from_i];
174c5c4113dSnw141292
175c5c4113dSnw141292 if (to_i >= buf_size - 1) {
176c5c4113dSnw141292 buf_size *= 2;
177c5c4113dSnw141292 buf = (char *)realloc(buf, buf_size * sizeof (char));
178c5c4113dSnw141292 }
179c5c4113dSnw141292
180c5c4113dSnw141292 if (c == '"' && !last_slash) {
181c5c4113dSnw141292 in_string = !in_string;
182c5c4113dSnw141292 is_param = 1;
183c5c4113dSnw141292 continue;
184c5c4113dSnw141292
185c5c4113dSnw141292 } else if (c == '\\' && !last_slash) {
186c5c4113dSnw141292 last_slash = 1;
187c5c4113dSnw141292 continue;
188c5c4113dSnw141292
189c5c4113dSnw141292 } else if (!last_slash && !in_string && isspace(c)) {
190c5c4113dSnw141292 break;
191c5c4113dSnw141292 }
192c5c4113dSnw141292
193c5c4113dSnw141292 buf[to_i++] = from[from_i];
194c5c4113dSnw141292 last_slash = 0;
195c5c4113dSnw141292
196c5c4113dSnw141292 }
197c5c4113dSnw141292
198c5c4113dSnw141292 if (to_i == 0 && !is_param) {
199c5c4113dSnw141292 free(buf);
200c5c4113dSnw141292 *to = NULL;
201c5c4113dSnw141292 return (0);
202c5c4113dSnw141292 }
203c5c4113dSnw141292
204c5c4113dSnw141292 buf[to_i] = '\0';
205c5c4113dSnw141292 *to = buf;
206c5c4113dSnw141292
207c5c4113dSnw141292 if (in_string)
208c5c4113dSnw141292 return (-1);
209c5c4113dSnw141292
210c5c4113dSnw141292 return (from_i);
211c5c4113dSnw141292 }
212c5c4113dSnw141292
213c5c4113dSnw141292 /*
214c5c4113dSnw141292 * Split a string to a parameter array and append it to the specified position
215c5c4113dSnw141292 * of the array
216c5c4113dSnw141292 */
217c5c4113dSnw141292 static int
line2array(const char * line)218c5c4113dSnw141292 line2array(const char *line)
219c5c4113dSnw141292 {
220c5c4113dSnw141292 const char *cur;
221c5c4113dSnw141292 char *param;
222c5c4113dSnw141292 int len;
223c5c4113dSnw141292
224c5c4113dSnw141292 for (cur = line; len = get_param(¶m, cur); cur += len) {
225*61b364a9Sjp151216 if (my_argc >= my_argv_size) {
226c5c4113dSnw141292 my_argv_size *= 2;
227c5c4113dSnw141292 my_argv = (char **)realloc(my_argv,
228c5c4113dSnw141292 my_argv_size * sizeof (char *));
229c5c4113dSnw141292 }
230c5c4113dSnw141292
231c5c4113dSnw141292 my_argv[my_argc] = param;
232c5c4113dSnw141292 ++my_argc;
233c5c4113dSnw141292
234c5c4113dSnw141292 /* quotation not closed */
235c5c4113dSnw141292 if (len < 0)
236c5c4113dSnw141292 return (-1);
237c5c4113dSnw141292
238c5c4113dSnw141292 }
239c5c4113dSnw141292 return (0);
240c5c4113dSnw141292
241c5c4113dSnw141292 }
242c5c4113dSnw141292
243c5c4113dSnw141292 /* Clean all aruments from my_argv. Don't deallocate my_argv itself. */
244c5c4113dSnw141292 static void
my_argv_clean()245c5c4113dSnw141292 my_argv_clean()
246c5c4113dSnw141292 {
247c5c4113dSnw141292 int i;
248c5c4113dSnw141292 for (i = 0; i < my_argc; i++) {
249c5c4113dSnw141292 free(my_argv[i]);
250c5c4113dSnw141292 my_argv[i] = NULL;
251c5c4113dSnw141292 }
252c5c4113dSnw141292 my_argc = 0;
253c5c4113dSnw141292 }
254c5c4113dSnw141292
255c5c4113dSnw141292
256c5c4113dSnw141292 #ifdef WITH_LIBTECLA
257c5c4113dSnw141292 /* This is libtecla tab completion. */
258c5c4113dSnw141292 static
CPL_MATCH_FN(command_complete)259c5c4113dSnw141292 CPL_MATCH_FN(command_complete)
260c5c4113dSnw141292 {
261c5c4113dSnw141292 /*
262c5c4113dSnw141292 * WordCompletion *cpl; const char *line; int word_end are
263c5c4113dSnw141292 * passed from the CPL_MATCH_FN macro.
264c5c4113dSnw141292 */
265c5c4113dSnw141292 int i;
266c5c4113dSnw141292 char *prefix;
267c5c4113dSnw141292 int prefix_l;
268c5c4113dSnw141292
269c5c4113dSnw141292 /* We go on even if quotation is not closed */
270c5c4113dSnw141292 (void) line2array(line);
271c5c4113dSnw141292
272c5c4113dSnw141292
273c5c4113dSnw141292 /* Beginning of the line: */
274c5c4113dSnw141292 if (my_argc == 0) {
275c5c4113dSnw141292 for (i = 0; i < my_comc; i++)
276c5c4113dSnw141292 (void) cpl_add_completion(cpl, line, word_end,
277c5c4113dSnw141292 word_end, my_comv[i].cmd, "", " ");
278c5c4113dSnw141292 goto cleanup;
279c5c4113dSnw141292 }
280c5c4113dSnw141292
281c5c4113dSnw141292 /* Is there something to complete? */
282c5c4113dSnw141292 if (isspace(line[word_end - 1]))
283c5c4113dSnw141292 goto cleanup;
284c5c4113dSnw141292
285c5c4113dSnw141292 prefix = my_argv[my_argc - 1];
286c5c4113dSnw141292 prefix_l = strlen(prefix);
287c5c4113dSnw141292
288c5c4113dSnw141292 /* Subcommand name: */
289c5c4113dSnw141292 if (my_argc == 1) {
290c5c4113dSnw141292 for (i = 0; i < my_comc; i++)
291c5c4113dSnw141292 if (strncmp(prefix, my_comv[i].cmd, prefix_l) == 0)
292c5c4113dSnw141292 (void) cpl_add_completion(cpl, line,
293c5c4113dSnw141292 word_end - prefix_l,
294c5c4113dSnw141292 word_end, my_comv[i].cmd + prefix_l,
295c5c4113dSnw141292 "", " ");
296c5c4113dSnw141292 goto cleanup;
297c5c4113dSnw141292 }
298c5c4113dSnw141292
299c5c4113dSnw141292 /* Long options: */
300c5c4113dSnw141292 if (prefix[0] == '-' && prefix [1] == '-') {
301c5c4113dSnw141292 char *options2 = NULL;
302c5c4113dSnw141292 char *paren;
303c5c4113dSnw141292 char *thesis;
304c5c4113dSnw141292 int i;
305c5c4113dSnw141292
306c5c4113dSnw141292 for (i = 0; i < my_comc; i++)
307c5c4113dSnw141292 if (0 == strcmp(my_comv[i].cmd, my_argv[0])) {
308c5c4113dSnw141292 options2 = strdup(my_comv[i].options);
309c5c4113dSnw141292 break;
310c5c4113dSnw141292 }
311c5c4113dSnw141292
312c5c4113dSnw141292 /* No such subcommand, or not enough memory: */
313c5c4113dSnw141292 if (options2 == NULL)
314c5c4113dSnw141292 goto cleanup;
315c5c4113dSnw141292
316c5c4113dSnw141292 for (paren = strchr(options2, '(');
317c5c4113dSnw141292 paren && ((thesis = strchr(paren + 1, ')')) != NULL);
318c5c4113dSnw141292 paren = strchr(thesis + 1, '(')) {
319c5c4113dSnw141292 /* Short option or thesis must precede, so this is safe: */
320c5c4113dSnw141292 *(paren - 1) = '-';
321c5c4113dSnw141292 *paren = '-';
322c5c4113dSnw141292 *thesis = '\0';
323c5c4113dSnw141292 if (strncmp(paren - 1, prefix, prefix_l) == 0) {
324c5c4113dSnw141292 (void) cpl_add_completion(cpl, line,
325c5c4113dSnw141292 word_end - prefix_l,
326c5c4113dSnw141292 word_end, paren - 1 + prefix_l, "", " ");
327c5c4113dSnw141292 }
328c5c4113dSnw141292 }
329c5c4113dSnw141292 free(options2);
330c5c4113dSnw141292
331c5c4113dSnw141292 /* "--" is a valid completion */
332c5c4113dSnw141292 if (prefix_l == 2) {
333c5c4113dSnw141292 (void) cpl_add_completion(cpl, line,
334c5c4113dSnw141292 word_end - 2,
335c5c4113dSnw141292 word_end, "", "", " ");
336c5c4113dSnw141292 }
337c5c4113dSnw141292
338c5c4113dSnw141292 }
339c5c4113dSnw141292
340c5c4113dSnw141292 cleanup:
341c5c4113dSnw141292 my_argv_clean();
342c5c4113dSnw141292 return (0);
343c5c4113dSnw141292 }
344c5c4113dSnw141292
345c5c4113dSnw141292 /* libtecla subshell: */
346c5c4113dSnw141292 static int
interactive_interp()347c5c4113dSnw141292 interactive_interp()
348c5c4113dSnw141292 {
349c5c4113dSnw141292 int rc = 0;
350c5c4113dSnw141292 char *prompt;
351c5c4113dSnw141292 const char *line;
352c5c4113dSnw141292
353c5c4113dSnw141292 (void) sigset(SIGINT, SIG_IGN);
354c5c4113dSnw141292
355c5c4113dSnw141292 gl_h = new_GetLine(MAX_CMD_LINE_SZ, MAX_HISTORY_LINES);
356c5c4113dSnw141292
357c5c4113dSnw141292 if (gl_h == NULL) {
358c5c4113dSnw141292 (void) fprintf(stderr,
359c5c4113dSnw141292 gettext("Error reading terminal: %s.\n"),
360c5c4113dSnw141292 gl_error_message(gl_h, NULL, 0));
361c5c4113dSnw141292 return (-1);
362c5c4113dSnw141292 }
363c5c4113dSnw141292
364c5c4113dSnw141292 (void) gl_customize_completion(gl_h, NULL, command_complete);
365c5c4113dSnw141292
366c5c4113dSnw141292 for (;;) {
367c5c4113dSnw141292 new_line:
368c5c4113dSnw141292 my_argv_clean();
369c5c4113dSnw141292 prompt = "> ";
370c5c4113dSnw141292 continue_line:
371c5c4113dSnw141292 line = gl_get_line(gl_h, prompt, NULL, -1);
372c5c4113dSnw141292
373c5c4113dSnw141292 if (line == NULL) {
374c5c4113dSnw141292 switch (gl_return_status(gl_h)) {
375c5c4113dSnw141292 case GLR_SIGNAL:
376c5c4113dSnw141292 gl_abandon_line(gl_h);
377c5c4113dSnw141292 goto new_line;
378c5c4113dSnw141292
379c5c4113dSnw141292 case GLR_EOF:
380c5c4113dSnw141292 (void) line2array("exit");
381c5c4113dSnw141292 break;
382c5c4113dSnw141292
383c5c4113dSnw141292 case GLR_ERROR:
384c5c4113dSnw141292 (void) fprintf(stderr,
385c5c4113dSnw141292 gettext("Error reading terminal: %s.\n"),
386c5c4113dSnw141292 gl_error_message(gl_h, NULL, 0));
387c5c4113dSnw141292 rc = -1;
388c5c4113dSnw141292 goto end_of_input;
389c5c4113dSnw141292 default:
390c5c4113dSnw141292 (void) fprintf(stderr, "Internal error.\n");
391c5c4113dSnw141292 exit(1);
392c5c4113dSnw141292 }
393c5c4113dSnw141292 } else {
394c5c4113dSnw141292 if (line2array(line) < 0) {
395c5c4113dSnw141292 (void) fprintf(stderr,
396c5c4113dSnw141292 gettext("Quotation not closed\n"));
397c5c4113dSnw141292 goto new_line;
398c5c4113dSnw141292 }
399c5c4113dSnw141292 if (my_argc == 0) {
400c5c4113dSnw141292 goto new_line;
401c5c4113dSnw141292 }
402c5c4113dSnw141292 if (strcmp(my_argv[my_argc-1], "\n") == 0) {
403c5c4113dSnw141292 my_argc--;
404c5c4113dSnw141292 free(my_argv[my_argc]);
405c5c4113dSnw141292 (void) strcpy(prompt, "> ");
406c5c4113dSnw141292 goto continue_line;
407c5c4113dSnw141292 }
408c5c4113dSnw141292 }
409c5c4113dSnw141292
4108e228215Sdm199847 rc = run_command(my_argc, my_argv, NULL);
411c5c4113dSnw141292
412c5c4113dSnw141292 if (strcmp(my_argv[0], "exit") == 0 && rc == 0) {
413c5c4113dSnw141292 break;
414c5c4113dSnw141292 }
415c5c4113dSnw141292
416c5c4113dSnw141292 }
417c5c4113dSnw141292
418c5c4113dSnw141292 end_of_input:
419c5c4113dSnw141292 gl_h = del_GetLine(gl_h);
420c5c4113dSnw141292 my_argv_clean();
421c5c4113dSnw141292 return (rc);
422c5c4113dSnw141292 }
423c5c4113dSnw141292 #endif
424c5c4113dSnw141292
425c5c4113dSnw141292 /* Interpretation of a source file given by "name" */
426c5c4113dSnw141292 static int
source_interp(const char * name)427c5c4113dSnw141292 source_interp(const char *name)
428c5c4113dSnw141292 {
429c5c4113dSnw141292 FILE *f;
430c5c4113dSnw141292 int is_stdin;
431c5c4113dSnw141292 int rc = -1;
432c5c4113dSnw141292 char line[MAX_CMD_LINE_SZ];
4338e228215Sdm199847 cmd_pos_t pos;
434c5c4113dSnw141292
435c5c4113dSnw141292 if (name == NULL || strcmp("-", name) == 0) {
436c5c4113dSnw141292 f = stdin;
437c5c4113dSnw141292 is_stdin = 1;
438c5c4113dSnw141292 } else {
439c5c4113dSnw141292 is_stdin = 0;
440c5c4113dSnw141292 f = fopen(name, "r");
441c5c4113dSnw141292 if (f == NULL) {
442c5c4113dSnw141292 perror(name);
443c5c4113dSnw141292 return (-1);
444c5c4113dSnw141292 }
445c5c4113dSnw141292 }
446c5c4113dSnw141292
4478e228215Sdm199847 pos.linenum = 0;
4488e228215Sdm199847 pos.line = line;
4498e228215Sdm199847
450c5c4113dSnw141292 while (fgets(line, MAX_CMD_LINE_SZ, f)) {
4518e228215Sdm199847 pos.linenum ++;
452c5c4113dSnw141292
453c5c4113dSnw141292 if (line2array(line) < 0) {
454c5c4113dSnw141292 (void) fprintf(stderr,
455c5c4113dSnw141292 gettext("Quotation not closed\n"));
456c5c4113dSnw141292 my_argv_clean();
457c5c4113dSnw141292 continue;
458c5c4113dSnw141292 }
459c5c4113dSnw141292
460c5c4113dSnw141292 /* We do not wan't "\n" as the last parameter */
461c5c4113dSnw141292 if (my_argc != 0 && strcmp(my_argv[my_argc-1], "\n") == 0) {
462c5c4113dSnw141292 my_argc--;
463c5c4113dSnw141292 free(my_argv[my_argc]);
464c5c4113dSnw141292 continue;
465c5c4113dSnw141292 }
466c5c4113dSnw141292
467c5c4113dSnw141292 if (my_argc != 0 && strcmp(my_argv[0], "exit") == 0) {
468c5c4113dSnw141292 rc = 0;
469c5c4113dSnw141292 my_argv_clean();
470c5c4113dSnw141292 break;
471c5c4113dSnw141292 }
472c5c4113dSnw141292
4738e228215Sdm199847 rc = run_command(my_argc, my_argv, &pos);
474c5c4113dSnw141292 my_argv_clean();
475c5c4113dSnw141292 }
476c5c4113dSnw141292
477c5c4113dSnw141292 if (my_argc > 0) {
478c5c4113dSnw141292 (void) fprintf(stderr, gettext("Line continuation missing\n"));
479c5c4113dSnw141292 rc = 1;
480c5c4113dSnw141292 my_argv_clean();
481c5c4113dSnw141292 }
482c5c4113dSnw141292
483c5c4113dSnw141292 if (!is_stdin)
484c5c4113dSnw141292 (void) fclose(f);
485c5c4113dSnw141292
486c5c4113dSnw141292 return (rc);
487c5c4113dSnw141292 }
488c5c4113dSnw141292
489c5c4113dSnw141292 /*
490c5c4113dSnw141292 * Initialize the engine.
491c5c4113dSnw141292 * comc, comv is the array of subcommands and its length,
492c5c4113dSnw141292 * argc, argv are arguments to main to be scanned for -f filename and
493c5c4113dSnw141292 * the length og the array,
494c5c4113dSnw141292 * is_batch_mode passes to the caller the information if the
495c5c4113dSnw141292 * batch mode is on.
496c5c4113dSnw141292 *
497c5c4113dSnw141292 * Return values:
498c5c4113dSnw141292 * 0: ... OK
499c5c4113dSnw141292 * IDMAP_ENG_ERROR: error and message printed already
500c5c4113dSnw141292 * IDMAP_ENG_ERROR_SILENT: error and message needs to be printed
501c5c4113dSnw141292 *
502c5c4113dSnw141292 */
503c5c4113dSnw141292
504c5c4113dSnw141292 int
engine_init(int comc,cmd_ops_t * comv,int argc,char ** argv,int * is_batch_mode)505c5c4113dSnw141292 engine_init(int comc, cmd_ops_t *comv, int argc, char **argv,
5064edd44c5Sjp151216 int *is_batch_mode)
5074edd44c5Sjp151216 {
508c5c4113dSnw141292 int c;
509c5c4113dSnw141292
510c5c4113dSnw141292 my_comc = comc;
511c5c4113dSnw141292 my_comv = comv;
512c5c4113dSnw141292
513c5c4113dSnw141292 my_argc = 0;
514c5c4113dSnw141292 my_argv = (char **)calloc(my_argv_size, sizeof (char *));
515c5c4113dSnw141292
516c5c4113dSnw141292 if (argc < 1) {
517c5c4113dSnw141292 my_filename = NULL;
518c5c4113dSnw141292 if (isatty(fileno(stdin))) {
519c5c4113dSnw141292 #ifdef WITH_LIBTECLA
520c5c4113dSnw141292 my_batch_mode = 1;
521c5c4113dSnw141292 #else
522c5c4113dSnw141292 my_batch_mode = 0;
523c5c4113dSnw141292 return (IDMAP_ENG_ERROR_SILENT);
524c5c4113dSnw141292 #endif
525c5c4113dSnw141292 } else
526c5c4113dSnw141292 my_batch_mode = 1;
527c5c4113dSnw141292
528c5c4113dSnw141292 goto the_end;
529c5c4113dSnw141292 }
530c5c4113dSnw141292
531c5c4113dSnw141292 my_batch_mode = 0;
532c5c4113dSnw141292
533c5c4113dSnw141292 optind = 0;
534c5c4113dSnw141292 while ((c = getopt(argc, argv,
535c5c4113dSnw141292 "f:(command-file)")) != EOF) {
536c5c4113dSnw141292 switch (c) {
537c5c4113dSnw141292 case '?':
538c5c4113dSnw141292 return (IDMAP_ENG_ERROR);
539c5c4113dSnw141292 case 'f':
540c5c4113dSnw141292 my_batch_mode = 1;
541c5c4113dSnw141292 my_filename = optarg;
542c5c4113dSnw141292 break;
543c5c4113dSnw141292 default:
544c5c4113dSnw141292 (void) fprintf(stderr, "Internal error.\n");
545c5c4113dSnw141292 exit(1);
546c5c4113dSnw141292 }
547c5c4113dSnw141292 }
548c5c4113dSnw141292
549c5c4113dSnw141292 the_end:
550c5c4113dSnw141292
551c5c4113dSnw141292 if (is_batch_mode != NULL)
552c5c4113dSnw141292 *is_batch_mode = my_batch_mode;
553c5c4113dSnw141292 return (0);
554c5c4113dSnw141292 }
555c5c4113dSnw141292
556c5c4113dSnw141292 /* finitialize the engine */
557c5c4113dSnw141292 int
engine_fini()5584edd44c5Sjp151216 engine_fini()
5594edd44c5Sjp151216 {
560c5c4113dSnw141292 my_argv_clean();
561c5c4113dSnw141292 free(my_argv);
562c5c4113dSnw141292 return (0);
563c5c4113dSnw141292 }
564c5c4113dSnw141292
565c5c4113dSnw141292 /*
566c5c4113dSnw141292 * Interpret the subcommands defined by the arguments, unless
567c5c4113dSnw141292 * my_batch_mode was set on in egnine_init.
568c5c4113dSnw141292 */
569c5c4113dSnw141292 int
run_engine(int argc,char ** argv)570c5c4113dSnw141292 run_engine(int argc, char **argv)
571c5c4113dSnw141292 {
572c5c4113dSnw141292 int rc = -1;
573c5c4113dSnw141292
574c5c4113dSnw141292 if (my_batch_mode) {
575c5c4113dSnw141292 #ifdef WITH_LIBTECLA
576c5c4113dSnw141292 if (isatty(fileno(stdin)))
577c5c4113dSnw141292 rc = interactive_interp();
578c5c4113dSnw141292 else
579c5c4113dSnw141292 #endif
580c5c4113dSnw141292 rc = source_interp(my_filename);
581c5c4113dSnw141292 goto cleanup;
582c5c4113dSnw141292 }
583c5c4113dSnw141292
5848e228215Sdm199847 rc = run_command(argc, argv, NULL);
585c5c4113dSnw141292
586c5c4113dSnw141292 cleanup:
587c5c4113dSnw141292 return (rc);
588c5c4113dSnw141292 }
589