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. 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 #ifdef HAVE_CONFIG_H 35 #include <config.h> 36 RCSID("$Id: sl.c,v 1.25 1999/12/02 16:58:55 joda Exp $"); 37 #endif 38 39 #include "sl_locl.h" 40 41 static SL_cmd * 42 sl_match (SL_cmd *cmds, char *cmd, int exactp) 43 { 44 SL_cmd *c, *current = NULL, *partial_cmd = NULL; 45 int partial_match = 0; 46 47 for (c = cmds; c->name; ++c) { 48 if (c->func) 49 current = c; 50 if (strcmp (cmd, c->name) == 0) 51 return current; 52 else if (strncmp (cmd, c->name, strlen(cmd)) == 0 && 53 partial_cmd != current) { 54 ++partial_match; 55 partial_cmd = current; 56 } 57 } 58 if (partial_match == 1 && !exactp) 59 return partial_cmd; 60 else 61 return NULL; 62 } 63 64 void 65 sl_help (SL_cmd *cmds, int argc, char **argv) 66 { 67 SL_cmd *c, *prev_c; 68 69 if (argc == 1) { 70 prev_c = NULL; 71 for (c = cmds; c->name; ++c) { 72 if (c->func) { 73 if(prev_c) 74 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "", 75 prev_c->usage ? "\n" : ""); 76 prev_c = c; 77 printf ("%s", c->name); 78 } else 79 printf (", %s", c->name); 80 } 81 if(prev_c) 82 printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "", 83 prev_c->usage ? "\n" : ""); 84 } else { 85 c = sl_match (cmds, argv[1], 0); 86 if (c == NULL) 87 printf ("No such command: %s. " 88 "Try \"help\" for a list of all commands\n", 89 argv[1]); 90 else { 91 printf ("%s\t%s\n", c->name, c->usage); 92 if(c->help && *c->help) 93 printf ("%s\n", c->help); 94 if((++c)->name && c->func == NULL) { 95 printf ("Synonyms:"); 96 while (c->name && c->func == NULL) 97 printf ("\t%s", (c++)->name); 98 printf ("\n"); 99 } 100 } 101 } 102 } 103 104 #ifdef HAVE_READLINE 105 106 char *readline(char *prompt); 107 void add_history(char *p); 108 109 #else 110 111 static char * 112 readline(char *prompt) 113 { 114 char buf[BUFSIZ]; 115 printf ("%s", prompt); 116 fflush (stdout); 117 if(fgets(buf, sizeof(buf), stdin) == NULL) 118 return NULL; 119 if (buf[strlen(buf) - 1] == '\n') 120 buf[strlen(buf) - 1] = '\0'; 121 return strdup(buf); 122 } 123 124 static void 125 add_history(char *p) 126 { 127 } 128 129 #endif 130 131 int 132 sl_command(SL_cmd *cmds, int argc, char **argv) 133 { 134 SL_cmd *c; 135 c = sl_match (cmds, argv[0], 0); 136 if (c == NULL) 137 return -1; 138 return (*c->func)(argc, argv); 139 } 140 141 struct sl_data { 142 int max_count; 143 char **ptr; 144 }; 145 146 int 147 sl_make_argv(char *line, int *ret_argc, char ***ret_argv) 148 { 149 char *foo = NULL; 150 char *p; 151 int argc, nargv; 152 char **argv; 153 154 nargv = 10; 155 argv = malloc(nargv * sizeof(*argv)); 156 if(argv == NULL) 157 return ENOMEM; 158 argc = 0; 159 160 for(p = strtok_r (line, " \t", &foo); 161 p; 162 p = strtok_r (NULL, " \t", &foo)) { 163 if(argc == nargv - 1) { 164 char **tmp; 165 nargv *= 2; 166 tmp = realloc (argv, nargv * sizeof(*argv)); 167 if (tmp == NULL) { 168 free(argv); 169 return ENOMEM; 170 } 171 argv = tmp; 172 } 173 argv[argc++] = p; 174 } 175 argv[argc] = NULL; 176 *ret_argc = argc; 177 *ret_argv = argv; 178 return 0; 179 } 180 181 /* return values: 0 on success, -1 on fatal error, or return value of command */ 182 int 183 sl_command_loop(SL_cmd *cmds, char *prompt, void **data) 184 { 185 int ret = 0; 186 char *buf; 187 int argc; 188 char **argv; 189 190 ret = 0; 191 buf = readline(prompt); 192 if(buf == NULL) 193 return 1; 194 195 if(*buf) 196 add_history(buf); 197 ret = sl_make_argv(buf, &argc, &argv); 198 if(ret) { 199 fprintf(stderr, "sl_loop: out of memory\n"); 200 free(buf); 201 return -1; 202 } 203 if (argc >= 1) { 204 ret = sl_command(cmds, argc, argv); 205 if(ret == -1) { 206 printf ("Unrecognized command: %s\n", argv[0]); 207 ret = 0; 208 } 209 } 210 free(buf); 211 free(argv); 212 return ret; 213 } 214 215 int 216 sl_loop(SL_cmd *cmds, char *prompt) 217 { 218 void *data = NULL; 219 int ret; 220 while((ret = sl_command_loop(cmds, prompt, &data)) == 0) 221 ; 222 return ret; 223 } 224