Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/sl/sl.c
34878 views
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.
12
*
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.
16
*
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.
20
*
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.
32
*/
33
34
#include <config.h>
35
36
#include "sl_locl.h"
37
#include <setjmp.h>
38
39
static void
40
mandoc_template(SL_cmd *cmds,
41
const char *extra_string)
42
{
43
SL_cmd *c, *prev;
44
char timestr[64], cmd[64];
45
const char *p;
46
time_t t;
47
48
printf(".\\\" Things to fix:\n");
49
printf(".\\\" * correct section, and operating system\n");
50
printf(".\\\" * remove Op from mandatory flags\n");
51
printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
52
printf(".\\\"\n");
53
t = time(NULL);
54
strftime(timestr, sizeof(timestr), "%b %d, %Y", localtime(&t));
55
printf(".Dd %s\n", timestr);
56
p = strrchr(getprogname(), '/');
57
if(p) p++; else p = getprogname();
58
strncpy(cmd, p, sizeof(cmd));
59
cmd[sizeof(cmd)-1] = '\0';
60
strupr(cmd);
61
62
printf(".Dt %s SECTION\n", cmd);
63
printf(".Os OPERATING_SYSTEM\n");
64
printf(".Sh NAME\n");
65
printf(".Nm %s\n", p);
66
printf(".Nd\n");
67
printf("in search of a description\n");
68
printf(".Sh SYNOPSIS\n");
69
printf(".Nm\n");
70
for(c = cmds; c->name; ++c) {
71
/* if (c->func == NULL)
72
continue; */
73
printf(".Op Fl %s", c->name);
74
printf("\n");
75
76
}
77
if (extra_string && *extra_string)
78
printf (".Ar %s\n", extra_string);
79
printf(".Sh DESCRIPTION\n");
80
printf("Supported options:\n");
81
printf(".Bl -tag -width Ds\n");
82
prev = NULL;
83
for(c = cmds; c->name; ++c) {
84
if (c->func) {
85
if (prev)
86
printf ("\n%s\n", prev->usage);
87
88
printf (".It Fl %s", c->name);
89
prev = c;
90
} else
91
printf (", %s\n", c->name);
92
}
93
if (prev)
94
printf ("\n%s\n", prev->usage);
95
96
printf(".El\n");
97
printf(".\\\".Sh ENVIRONMENT\n");
98
printf(".\\\".Sh FILES\n");
99
printf(".\\\".Sh EXAMPLES\n");
100
printf(".\\\".Sh DIAGNOSTICS\n");
101
printf(".\\\".Sh SEE ALSO\n");
102
printf(".\\\".Sh STANDARDS\n");
103
printf(".\\\".Sh HISTORY\n");
104
printf(".\\\".Sh AUTHORS\n");
105
printf(".\\\".Sh BUGS\n");
106
}
107
108
SL_cmd *
109
sl_match (SL_cmd *cmds, char *cmd, int exactp)
110
{
111
SL_cmd *c, *current = NULL, *partial_cmd = NULL;
112
int partial_match = 0;
113
114
for (c = cmds; c->name; ++c) {
115
if (c->func)
116
current = c;
117
if (strcmp (cmd, c->name) == 0)
118
return current;
119
else if (strncmp (cmd, c->name, strlen(cmd)) == 0 &&
120
partial_cmd != current) {
121
++partial_match;
122
partial_cmd = current;
123
}
124
}
125
if (partial_match == 1 && !exactp)
126
return partial_cmd;
127
else
128
return NULL;
129
}
130
131
void
132
sl_help (SL_cmd *cmds, int argc, char **argv)
133
{
134
SL_cmd *c, *prev_c;
135
136
if (getenv("SLMANDOC")) {
137
mandoc_template(cmds, NULL);
138
return;
139
}
140
141
if (argc == 1) {
142
prev_c = NULL;
143
for (c = cmds; c->name; ++c) {
144
if (c->func) {
145
if(prev_c)
146
printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
147
prev_c->usage ? "\n" : "");
148
prev_c = c;
149
printf ("%s", c->name);
150
} else
151
printf (", %s", c->name);
152
}
153
if(prev_c)
154
printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
155
prev_c->usage ? "\n" : "");
156
} else {
157
c = sl_match (cmds, argv[1], 0);
158
if (c == NULL)
159
printf ("No such command: %s. "
160
"Try \"help\" for a list of all commands\n",
161
argv[1]);
162
else {
163
printf ("%s\t%s\n", c->name, c->usage);
164
if(c->help && *c->help)
165
printf ("%s\n", c->help);
166
if((++c)->name && c->func == NULL) {
167
printf ("Synonyms:");
168
while (c->name && c->func == NULL)
169
printf ("\t%s", (c++)->name);
170
printf ("\n");
171
}
172
}
173
}
174
}
175
176
#ifdef HAVE_READLINE
177
178
char *readline(char *prompt);
179
void add_history(char *p);
180
181
#else
182
183
static char *
184
readline(char *prompt)
185
{
186
char buf[BUFSIZ];
187
printf ("%s", prompt);
188
fflush (stdout);
189
if(fgets(buf, sizeof(buf), stdin) == NULL)
190
return NULL;
191
buf[strcspn(buf, "\r\n")] = '\0';
192
return strdup(buf);
193
}
194
195
static void
196
add_history(char *p)
197
{
198
}
199
200
#endif
201
202
int
203
sl_command(SL_cmd *cmds, int argc, char **argv)
204
{
205
SL_cmd *c;
206
c = sl_match (cmds, argv[0], 0);
207
if (c == NULL)
208
return -1;
209
return (*c->func)(argc, argv);
210
}
211
212
struct sl_data {
213
int max_count;
214
char **ptr;
215
};
216
217
int
218
sl_make_argv(char *line, int *ret_argc, char ***ret_argv)
219
{
220
char *p, *begining;
221
int argc, nargv;
222
char **argv;
223
int quote = 0;
224
225
nargv = 10;
226
argv = malloc(nargv * sizeof(*argv));
227
if(argv == NULL)
228
return ENOMEM;
229
argc = 0;
230
231
p = line;
232
233
while(isspace((unsigned char)*p))
234
p++;
235
begining = p;
236
237
while (1) {
238
if (*p == '\0') {
239
;
240
} else if (*p == '"') {
241
quote = !quote;
242
memmove(&p[0], &p[1], strlen(&p[1]) + 1);
243
continue;
244
} else if (*p == '\\') {
245
if (p[1] == '\0')
246
goto failed;
247
memmove(&p[0], &p[1], strlen(&p[1]) + 1);
248
p += 2;
249
continue;
250
} else if (quote || !isspace((unsigned char)*p)) {
251
p++;
252
continue;
253
} else
254
*p++ = '\0';
255
if (quote)
256
goto failed;
257
if(argc == nargv - 1) {
258
char **tmp;
259
nargv *= 2;
260
tmp = realloc (argv, nargv * sizeof(*argv));
261
if (tmp == NULL) {
262
free(argv);
263
return ENOMEM;
264
}
265
argv = tmp;
266
}
267
argv[argc++] = begining;
268
while(isspace((unsigned char)*p))
269
p++;
270
if (*p == '\0')
271
break;
272
begining = p;
273
}
274
argv[argc] = NULL;
275
*ret_argc = argc;
276
*ret_argv = argv;
277
return 0;
278
failed:
279
free(argv);
280
return ERANGE;
281
}
282
283
static jmp_buf sl_jmp;
284
285
static void sl_sigint(int sig)
286
{
287
longjmp(sl_jmp, 1);
288
}
289
290
static char *sl_readline(const char *prompt)
291
{
292
char *s;
293
void (*old)(int);
294
old = signal(SIGINT, sl_sigint);
295
if(setjmp(sl_jmp))
296
printf("\n");
297
s = readline(rk_UNCONST(prompt));
298
signal(SIGINT, old);
299
return s;
300
}
301
302
/* return values:
303
* 0 on success,
304
* -1 on fatal error,
305
* -2 if EOF, or
306
* return value of command */
307
int
308
sl_command_loop(SL_cmd *cmds, const char *prompt, void **data)
309
{
310
int ret = 0;
311
char *buf;
312
int argc;
313
char **argv;
314
315
buf = sl_readline(prompt);
316
if(buf == NULL)
317
return -2;
318
319
if(*buf)
320
add_history(buf);
321
ret = sl_make_argv(buf, &argc, &argv);
322
if(ret) {
323
fprintf(stderr, "sl_loop: out of memory\n");
324
free(buf);
325
return -1;
326
}
327
if (argc >= 1) {
328
ret = sl_command(cmds, argc, argv);
329
if(ret == -1) {
330
printf ("Unrecognized command: %s\n", argv[0]);
331
ret = 0;
332
}
333
}
334
free(buf);
335
free(argv);
336
return ret;
337
}
338
339
int
340
sl_loop(SL_cmd *cmds, const char *prompt)
341
{
342
void *data = NULL;
343
int ret;
344
while((ret = sl_command_loop(cmds, prompt, &data)) >= 0)
345
;
346
return ret;
347
}
348
349
void
350
sl_apropos (SL_cmd *cmd, const char *topic)
351
{
352
for (; cmd->name != NULL; ++cmd)
353
if (cmd->usage != NULL && strstr(cmd->usage, topic) != NULL)
354
printf ("%-20s%s\n", cmd->name, cmd->usage);
355
}
356
357
/*
358
* Help to be used with slc.
359
*/
360
361
void
362
sl_slc_help (SL_cmd *cmds, int argc, char **argv)
363
{
364
if(argc == 0) {
365
sl_help(cmds, 1, argv - 1 /* XXX */);
366
} else {
367
SL_cmd *c = sl_match (cmds, argv[0], 0);
368
if(c == NULL) {
369
fprintf (stderr, "No such command: %s. "
370
"Try \"help\" for a list of commands\n",
371
argv[0]);
372
} else {
373
if(c->func) {
374
static char help[] = "--help";
375
char *fake[3];
376
fake[0] = argv[0];
377
fake[1] = help;
378
fake[2] = NULL;
379
(*c->func)(2, fake);
380
fprintf(stderr, "\n");
381
}
382
if(c->help && *c->help)
383
fprintf (stderr, "%s\n", c->help);
384
if((++c)->name && c->func == NULL) {
385
int f = 0;
386
fprintf (stderr, "Synonyms:");
387
while (c->name && c->func == NULL) {
388
fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
389
f = 1;
390
}
391
fprintf (stderr, "\n");
392
}
393
}
394
}
395
}
396
397