This commit was manufactured by cvs2svn to create tag
[heimdal.git] / lib / sl / sl.c
blob7aa691973deb46782118c21819b5ddc59a073ecc
1 /*
2 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 RCSID("$Id$");
42 #endif
44 #include "sl_locl.h"
46 static SL_cmd *
47 sl_match (SL_cmd *cmds, char *cmd, int exactp)
49 SL_cmd *c, *current = NULL, *partial_cmd = NULL;
50 int partial_match = 0;
52 for (c = cmds; c->name; ++c) {
53 if (c->func)
54 current = c;
55 if (strcmp (cmd, c->name) == 0)
56 return current;
57 else if (strncmp (cmd, c->name, strlen(cmd)) == 0 &&
58 partial_cmd != current) {
59 ++partial_match;
60 partial_cmd = current;
63 if (partial_match == 1 && !exactp)
64 return partial_cmd;
65 else
66 return NULL;
69 void
70 sl_help (SL_cmd *cmds, int argc, char **argv)
72 SL_cmd *c, *prev_c;
74 if (argc == 1) {
75 prev_c = NULL;
76 for (c = cmds; c->name; ++c) {
77 if (c->func) {
78 if(prev_c)
79 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
80 prev_c->usage ? "\n" : "");
81 prev_c = c;
82 printf ("%s", c->name);
83 } else
84 printf (", %s", c->name);
86 if(prev_c)
87 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
88 prev_c->usage ? "\n" : "");
89 } else {
90 c = sl_match (cmds, argv[1], 0);
91 if (c == NULL)
92 printf ("No such command: %s. "
93 "Try \"help\" for a list of all commands\n",
94 argv[1]);
95 else {
96 printf ("%s\t%s\n", c->name, c->usage);
97 if(c->help && *c->help)
98 printf ("%s\n", c->help);
99 if((++c)->name && c->func == NULL) {
100 printf ("Synonyms:");
101 while (c->name && c->func == NULL)
102 printf ("\t%s", (c++)->name);
103 printf ("\n");
109 #ifdef HAVE_READLINE
111 char *readline(char *prompt);
112 void add_history(char *p);
114 #else
116 static char *
117 readline(char *prompt)
119 char buf[BUFSIZ];
120 printf ("%s", prompt);
121 fflush (stdout);
122 if(fgets(buf, sizeof(buf), stdin) == NULL)
123 return NULL;
124 if (buf[strlen(buf) - 1] == '\n')
125 buf[strlen(buf) - 1] = '\0';
126 return strdup(buf);
129 static void
130 add_history(char *p)
134 #endif
137 sl_command(SL_cmd *cmds, int argc, char **argv)
139 SL_cmd *c;
140 c = sl_match (cmds, argv[0], 0);
141 if (c == NULL)
142 return -1;
143 return (*c->func)(argc, argv);
146 struct sl_data {
147 int max_count;
148 char **ptr;
152 sl_make_argv(char *line, int *ret_argc, char ***ret_argv)
154 char *foo = NULL;
155 char *p;
156 int argc, nargv;
157 char **argv;
159 nargv = 10;
160 argv = malloc(nargv * sizeof(*argv));
161 if(argv == NULL)
162 return ENOMEM;
163 argc = 0;
165 for(p = strtok_r (line, " \t", &foo);
167 p = strtok_r (NULL, " \t", &foo)) {
168 if(argc == nargv - 1) {
169 char **tmp;
170 nargv *= 2;
171 tmp = realloc (argv, nargv * sizeof(*argv));
172 if (tmp == NULL) {
173 free(argv);
174 return ENOMEM;
176 argv = tmp;
178 argv[argc++] = p;
180 argv[argc] = NULL;
181 *ret_argc = argc;
182 *ret_argv = argv;
183 return 0;
186 /* return values: 0 on success, -1 on fatal error, or return value of command */
188 sl_command_loop(SL_cmd *cmds, char *prompt, void **data)
190 int ret = 0;
191 char *buf;
192 int argc;
193 char **argv;
195 ret = 0;
196 buf = readline(prompt);
197 if(buf == NULL)
198 return 1;
200 if(*buf)
201 add_history(buf);
202 ret = sl_make_argv(buf, &argc, &argv);
203 if(ret) {
204 fprintf(stderr, "sl_loop: out of memory\n");
205 free(buf);
206 return -1;
208 if (argc >= 1) {
209 ret = sl_command(cmds, argc, argv);
210 if(ret == -1) {
211 printf ("Unrecognized command: %s\n", argv[0]);
212 ret = 0;
215 free(buf);
216 free(argv);
217 return ret;
220 int
221 sl_loop(SL_cmd *cmds, char *prompt)
223 void *data = NULL;
224 int ret;
225 while((ret = sl_command_loop(cmds, prompt, &data)) == 0)
227 return ret;