No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / sl / sl.c
blob0ea42fe32d612504355294fd6826b5bd0933cc75
1 /*
2 * Copyright (c) 1995 - 2006 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. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 THE INSTITUTE 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.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 __RCSID("$Heimdal: sl.c 21160 2007-06-18 22:58:21Z lha $"
37 "$NetBSD$");
38 #endif
40 #include "sl_locl.h"
41 #include <setjmp.h>
43 static void
44 mandoc_template(SL_cmd *cmds,
45 const char *extra_string)
47 SL_cmd *c, *prev;
48 char timestr[64], cmd[64];
49 const char *p;
50 time_t t;
52 printf(".\\\" Things to fix:\n");
53 printf(".\\\" * correct section, and operating system\n");
54 printf(".\\\" * remove Op from mandatory flags\n");
55 printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
56 printf(".\\\"\n");
57 t = time(NULL);
58 strftime(timestr, sizeof(timestr), "%b %d, %Y", localtime(&t));
59 printf(".Dd %s\n", timestr);
60 p = strrchr(getprogname(), '/');
61 if(p) p++; else p = getprogname();
62 strncpy(cmd, p, sizeof(cmd));
63 cmd[sizeof(cmd)-1] = '\0';
64 strupr(cmd);
66 printf(".Dt %s SECTION\n", cmd);
67 printf(".Os OPERATING_SYSTEM\n");
68 printf(".Sh NAME\n");
69 printf(".Nm %s\n", p);
70 printf(".Nd\n");
71 printf("in search of a description\n");
72 printf(".Sh SYNOPSIS\n");
73 printf(".Nm\n");
74 for(c = cmds; c->name; ++c) {
75 /* if (c->func == NULL)
76 continue; */
77 printf(".Op Fl %s", c->name);
78 printf("\n");
81 if (extra_string && *extra_string)
82 printf (".Ar %s\n", extra_string);
83 printf(".Sh DESCRIPTION\n");
84 printf("Supported options:\n");
85 printf(".Bl -tag -width Ds\n");
86 prev = NULL;
87 for(c = cmds; c->name; ++c) {
88 if (c->func) {
89 if (prev)
90 printf ("\n%s\n", prev->usage);
92 printf (".It Fl %s", c->name);
93 prev = c;
94 } else
95 printf (", %s\n", c->name);
97 if (prev)
98 printf ("\n%s\n", prev->usage);
100 printf(".El\n");
101 printf(".\\\".Sh ENVIRONMENT\n");
102 printf(".\\\".Sh FILES\n");
103 printf(".\\\".Sh EXAMPLES\n");
104 printf(".\\\".Sh DIAGNOSTICS\n");
105 printf(".\\\".Sh SEE ALSO\n");
106 printf(".\\\".Sh STANDARDS\n");
107 printf(".\\\".Sh HISTORY\n");
108 printf(".\\\".Sh AUTHORS\n");
109 printf(".\\\".Sh BUGS\n");
112 SL_cmd *
113 sl_match (SL_cmd *cmds, char *cmd, int exactp)
115 SL_cmd *c, *current = NULL, *partial_cmd = NULL;
116 int partial_match = 0;
118 for (c = cmds; c->name; ++c) {
119 if (c->func)
120 current = c;
121 if (strcmp (cmd, c->name) == 0)
122 return current;
123 else if (strncmp (cmd, c->name, strlen(cmd)) == 0 &&
124 partial_cmd != current) {
125 ++partial_match;
126 partial_cmd = current;
129 if (partial_match == 1 && !exactp)
130 return partial_cmd;
131 else
132 return NULL;
135 void
136 sl_help (SL_cmd *cmds, int argc, char **argv)
138 SL_cmd *c, *prev_c;
140 if (getenv("SLMANDOC")) {
141 mandoc_template(cmds, NULL);
142 return;
145 if (argc == 1) {
146 prev_c = NULL;
147 for (c = cmds; c->name; ++c) {
148 if (c->func) {
149 if(prev_c)
150 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
151 prev_c->usage ? "\n" : "");
152 prev_c = c;
153 printf ("%s", c->name);
154 } else
155 printf (", %s", c->name);
157 if(prev_c)
158 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
159 prev_c->usage ? "\n" : "");
160 } else {
161 c = sl_match (cmds, argv[1], 0);
162 if (c == NULL)
163 printf ("No such command: %s. "
164 "Try \"help\" for a list of all commands\n",
165 argv[1]);
166 else {
167 printf ("%s\t%s\n", c->name, c->usage);
168 if(c->help && *c->help)
169 printf ("%s\n", c->help);
170 if((++c)->name && c->func == NULL) {
171 printf ("Synonyms:");
172 while (c->name && c->func == NULL)
173 printf ("\t%s", (c++)->name);
174 printf ("\n");
180 #ifdef HAVE_READLINE
182 char *readline(char *prompt);
183 void add_history(char *p);
185 #else
187 static char *
188 readline(char *prompt)
190 char buf[BUFSIZ];
191 printf ("%s", prompt);
192 fflush (stdout);
193 if(fgets(buf, sizeof(buf), stdin) == NULL)
194 return NULL;
195 buf[strcspn(buf, "\r\n")] = '\0';
196 return strdup(buf);
199 static void
200 add_history(char *p)
204 #endif
207 sl_command(SL_cmd *cmds, int argc, char **argv)
209 SL_cmd *c;
210 c = sl_match (cmds, argv[0], 0);
211 if (c == NULL)
212 return -1;
213 return (*c->func)(argc, argv);
216 struct sl_data {
217 int max_count;
218 char **ptr;
222 sl_make_argv(char *line, int *ret_argc, char ***ret_argv)
224 char *p, *begining;
225 int argc, nargv;
226 char **argv;
227 int quote = 0;
229 nargv = 10;
230 argv = malloc(nargv * sizeof(*argv));
231 if(argv == NULL)
232 return ENOMEM;
233 argc = 0;
235 p = line;
237 while(isspace((unsigned char)*p))
238 p++;
239 begining = p;
241 while (1) {
242 if (*p == '\0') {
244 } else if (*p == '"') {
245 quote = !quote;
246 memmove(&p[0], &p[1], strlen(&p[1]) + 1);
247 continue;
248 } else if (*p == '\\') {
249 if (p[1] == '\0')
250 goto failed;
251 memmove(&p[0], &p[1], strlen(&p[1]) + 1);
252 p += 2;
253 continue;
254 } else if (quote || !isspace((unsigned char)*p)) {
255 p++;
256 continue;
257 } else
258 *p++ = '\0';
259 if (quote)
260 goto failed;
261 if(argc == nargv - 1) {
262 char **tmp;
263 nargv *= 2;
264 tmp = realloc (argv, nargv * sizeof(*argv));
265 if (tmp == NULL) {
266 free(argv);
267 return ENOMEM;
269 argv = tmp;
271 argv[argc++] = begining;
272 while(isspace((unsigned char)*p))
273 p++;
274 if (*p == '\0')
275 break;
276 begining = p;
278 argv[argc] = NULL;
279 *ret_argc = argc;
280 *ret_argv = argv;
281 return 0;
282 failed:
283 free(argv);
284 return ERANGE;
287 static jmp_buf sl_jmp;
289 static void sl_sigint(int sig)
291 longjmp(sl_jmp, 1);
294 static char *sl_readline(const char *prompt)
296 char *s;
297 void (*old)(int);
298 old = signal(SIGINT, sl_sigint);
299 if(setjmp(sl_jmp))
300 printf("\n");
301 s = readline(rk_UNCONST(prompt));
302 signal(SIGINT, old);
303 return s;
306 /* return values:
307 * 0 on success,
308 * -1 on fatal error,
309 * -2 if EOF, or
310 * return value of command */
312 sl_command_loop(SL_cmd *cmds, const char *prompt, void **data)
314 int ret = 0;
315 char *buf;
316 int argc;
317 char **argv;
319 ret = 0;
320 buf = sl_readline(prompt);
321 if(buf == NULL)
322 return -2;
324 if(*buf)
325 add_history(buf);
326 ret = sl_make_argv(buf, &argc, &argv);
327 if(ret) {
328 fprintf(stderr, "sl_loop: out of memory\n");
329 free(buf);
330 return -1;
332 if (argc >= 1) {
333 ret = sl_command(cmds, argc, argv);
334 if(ret == -1) {
335 printf ("Unrecognized command: %s\n", argv[0]);
336 ret = 0;
339 free(buf);
340 free(argv);
341 return ret;
344 int
345 sl_loop(SL_cmd *cmds, const char *prompt)
347 void *data = NULL;
348 int ret;
349 while((ret = sl_command_loop(cmds, prompt, &data)) >= 0)
351 return ret;
354 void
355 sl_apropos (SL_cmd *cmd, const char *topic)
357 for (; cmd->name != NULL; ++cmd)
358 if (cmd->usage != NULL && strstr(cmd->usage, topic) != NULL)
359 printf ("%-20s%s\n", cmd->name, cmd->usage);
363 * Help to be used with slc.
366 void
367 sl_slc_help (SL_cmd *cmds, int argc, char **argv)
369 if(argc == 0) {
370 sl_help(cmds, 1, argv - 1 /* XXX */);
371 } else {
372 SL_cmd *c = sl_match (cmds, argv[0], 0);
373 if(c == NULL) {
374 fprintf (stderr, "No such command: %s. "
375 "Try \"help\" for a list of commands\n",
376 argv[0]);
377 } else {
378 if(c->func) {
379 char *fake[] = { NULL, "--help", NULL };
380 fake[0] = argv[0];
381 (*c->func)(2, fake);
382 fprintf(stderr, "\n");
384 if(c->help && *c->help)
385 fprintf (stderr, "%s\n", c->help);
386 if((++c)->name && c->func == NULL) {
387 int f = 0;
388 fprintf (stderr, "Synonyms:");
389 while (c->name && c->func == NULL) {
390 fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
391 f = 1;
393 fprintf (stderr, "\n");