el.c revision 84260
1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * 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. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $NetBSD: el.c,v 1.20 2000/11/11 22:18:57 christos Exp $ 37 */ 38 39#if !defined(lint) && !defined(SCCSID) 40static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; 41#endif /* not lint && not SCCSID */ 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/lib/libedit/el.c 84260 2001-10-01 08:41:27Z obrien $"); 44 45/* 46 * el.c: EditLine interface functions 47 */ 48#include "sys.h" 49 50#include <sys/types.h> 51#include <sys/param.h> 52#include <string.h> 53#include <stdlib.h> 54#include <stdarg.h> 55#include "el.h" 56 57/* el_init(): 58 * Initialize editline and set default parameters. 59 */ 60public EditLine * 61el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) 62{ 63 64 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); 65#ifdef DEBUG 66 char *tty; 67#endif 68 69 if (el == NULL) 70 return (NULL); 71 72 memset(el, 0, sizeof(EditLine)); 73 74 el->el_infd = fileno(fin); 75 el->el_outfile = fout; 76 el->el_errfile = ferr; 77 el->el_prog = strdup(prog); 78 79 /* 80 * Initialize all the modules. Order is important!!! 81 */ 82 el->el_flags = 0; 83 84 (void) term_init(el); 85 (void) key_init(el); 86 (void) map_init(el); 87 if (tty_init(el) == -1) 88 el->el_flags |= NO_TTY; 89 (void) ch_init(el); 90 (void) search_init(el); 91 (void) hist_init(el); 92 (void) prompt_init(el); 93 (void) sig_init(el); 94 el->data = NULL; 95 96 return (el); 97} 98 99 100/* el_end(): 101 * Clean up. 102 */ 103public void 104el_end(EditLine *el) 105{ 106 107 if (el == NULL) 108 return; 109 110 el_reset(el); 111 112 term_end(el); 113 key_end(el); 114 map_end(el); 115 tty_end(el); 116 ch_end(el); 117 search_end(el); 118 hist_end(el); 119 prompt_end(el); 120 sig_end(el); 121 122 el_free((ptr_t) el->el_prog); 123 el_free((ptr_t) el); 124} 125 126 127/* el_reset(): 128 * Reset the tty and the parser 129 */ 130public void 131el_reset(EditLine *el) 132{ 133 134 tty_cookedmode(el); 135 ch_reset(el); /* XXX: Do we want that? */ 136} 137 138 139/* el_set(): 140 * set the editline parameters 141 */ 142public int 143el_set(EditLine *el, int op, ...) 144{ 145 va_list va; 146 int rv; 147 va_start(va, op); 148 149 if (el == NULL) 150 return (-1); 151 switch (op) { 152 case EL_PROMPT: 153 case EL_RPROMPT: 154 rv = prompt_set(el, va_arg(va, el_pfunc_t), op); 155 break; 156 157 case EL_TERMINAL: 158 rv = term_set(el, va_arg(va, char *)); 159 break; 160 161 case EL_EDITOR: 162 rv = map_set_editor(el, va_arg(va, char *)); 163 break; 164 165 case EL_SIGNAL: 166 if (va_arg(va, int)) 167 el->el_flags |= HANDLE_SIGNALS; 168 else 169 el->el_flags &= ~HANDLE_SIGNALS; 170 rv = 0; 171 break; 172 173 case EL_BIND: 174 case EL_TELLTC: 175 case EL_SETTC: 176 case EL_ECHOTC: 177 case EL_SETTY: 178 { 179 char *argv[20]; 180 int i; 181 182 for (i = 1; i < 20; i++) 183 if ((argv[i] = va_arg(va, char *)) == NULL) 184 break; 185 186 switch (op) { 187 case EL_BIND: 188 argv[0] = "bind"; 189 rv = map_bind(el, i, argv); 190 break; 191 192 case EL_TELLTC: 193 argv[0] = "telltc"; 194 rv = term_telltc(el, i, argv); 195 break; 196 197 case EL_SETTC: 198 argv[0] = "settc"; 199 rv = term_settc(el, i, argv); 200 break; 201 202 case EL_ECHOTC: 203 argv[0] = "echotc"; 204 rv = term_echotc(el, i, argv); 205 break; 206 207 case EL_SETTY: 208 argv[0] = "setty"; 209 rv = tty_stty(el, i, argv); 210 break; 211 212 default: 213 rv = -1; 214 EL_ABORT((el->el_errfile, "Bad op %d\n", op)); 215 break; 216 } 217 break; 218 } 219 220 case EL_ADDFN: 221 { 222 char *name = va_arg(va, char *); 223 char *help = va_arg(va, char *); 224 el_func_t func = va_arg(va, el_func_t); 225 226 rv = map_addfunc(el, name, help, func); 227 break; 228 } 229 230 case EL_HIST: 231 { 232 hist_fun_t func = va_arg(va, hist_fun_t); 233 ptr_t ptr = va_arg(va, char *); 234 235 rv = hist_set(el, func, ptr); 236 break; 237 } 238 239 case EL_EDITMODE: 240 if (va_arg(va, int)) 241 el->el_flags &= ~EDIT_DISABLED; 242 else 243 el->el_flags |= EDIT_DISABLED; 244 rv = 0; 245 break; 246 247 default: 248 rv = -1; 249 } 250 251 va_end(va); 252 return (rv); 253} 254 255 256/* el_get(): 257 * retrieve the editline parameters 258 */ 259public int 260el_get(EditLine *el, int op, void *ret) 261{ 262 int rv; 263 264 if (el == NULL || ret == NULL) 265 return (-1); 266 switch (op) { 267 case EL_PROMPT: 268 case EL_RPROMPT: 269 rv = prompt_get(el, (el_pfunc_t *) & ret, op); 270 break; 271 272 case EL_EDITOR: 273 rv = map_get_editor(el, (const char **) &ret); 274 break; 275 276 case EL_SIGNAL: 277 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS); 278 rv = 0; 279 break; 280 281 case EL_EDITMODE: 282 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED)); 283 rv = 0; 284 break; 285 286#if 0 /* XXX */ 287 case EL_TERMINAL: 288 rv = term_get(el, (const char *) &ret); 289 break; 290 291 case EL_BIND: 292 case EL_TELLTC: 293 case EL_SETTC: 294 case EL_ECHOTC: 295 case EL_SETTY: 296 { 297 char *argv[20]; 298 int i; 299 300 for (i = 1; i < 20; i++) 301 if ((argv[i] = va_arg(va, char *)) == NULL) 302 break; 303 304 switch (op) { 305 case EL_BIND: 306 argv[0] = "bind"; 307 rv = map_bind(el, i, argv); 308 break; 309 310 case EL_TELLTC: 311 argv[0] = "telltc"; 312 rv = term_telltc(el, i, argv); 313 break; 314 315 case EL_SETTC: 316 argv[0] = "settc"; 317 rv = term_settc(el, i, argv); 318 break; 319 320 case EL_ECHOTC: 321 argv[0] = "echotc"; 322 rv = term_echotc(el, i, argv); 323 break; 324 325 case EL_SETTY: 326 argv[0] = "setty"; 327 rv = tty_stty(el, i, argv); 328 break; 329 330 default: 331 rv = -1; 332 EL_ABORT((el->errfile, "Bad op %d\n", op)); 333 break; 334 } 335 break; 336} 337 338public void 339el_data_set (el, data) 340 EditLine *el; 341 void *data; 342{ 343 el->data = data; 344 345 return; 346} 347 348public void * 349el_data_get (el) 350 EditLine *el; 351{ 352 if (el->data) 353 return (el->data); 354 return (NULL); 355 } 356 357 case EL_ADDFN: 358 { 359 char *name = va_arg(va, char *); 360 char *help = va_arg(va, char *); 361 el_func_t func = va_arg(va, el_func_t); 362 363 rv = map_addfunc(el, name, help, func); 364 break; 365 } 366 367 case EL_HIST: 368 { 369 hist_fun_t func = va_arg(va, hist_fun_t); 370 ptr_t ptr = va_arg(va, char *); 371 rv = hist_set(el, func, ptr); 372 } 373 break; 374#endif /* XXX */ 375 376 default: 377 rv = -1; 378 } 379 380 return (rv); 381} 382 383 384/* el_line(): 385 * Return editing info 386 */ 387public const LineInfo * 388el_line(EditLine *el) 389{ 390 391 return (const LineInfo *) (void *) &el->el_line; 392} 393 394static const char elpath[] = "/.editrc"; 395 396/* el_source(): 397 * Source a file 398 */ 399public int 400el_source(EditLine *el, const char *fname) 401{ 402 FILE *fp; 403 size_t len; 404 char *ptr, path[MAXPATHLEN]; 405 406 fp = NULL; 407 if (fname == NULL) { 408 if (issetugid()) 409 return (-1); 410 if ((ptr = getenv("HOME")) == NULL) 411 return (-1); 412 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) 413 return (-1); 414 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) 415 return (-1); 416 fname = path; 417 } 418 if (fp == NULL) 419 fp = fopen(fname, "r"); 420 if (fp == NULL) 421 return (-1); 422 423 while ((ptr = fgetln(fp, &len)) != NULL) { 424 if (len > 0 && ptr[len - 1] == '\n') 425 --len; 426 ptr[len] = '\0'; 427 if (parse_line(el, ptr) == -1) { 428 (void) fclose(fp); 429 return (-1); 430 } 431 } 432 433 (void) fclose(fp); 434 return (0); 435} 436 437 438/* el_resize(): 439 * Called from program when terminal is resized 440 */ 441public void 442el_resize(EditLine *el) 443{ 444 int lins, cols; 445 sigset_t oset, nset; 446 447 (void) sigemptyset(&nset); 448 (void) sigaddset(&nset, SIGWINCH); 449 (void) sigprocmask(SIG_BLOCK, &nset, &oset); 450 451 /* get the correct window size */ 452 if (term_get_size(el, &lins, &cols)) 453 term_change_size(el, lins, cols); 454 455 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 456} 457 458 459/* el_beep(): 460 * Called from the program to beep 461 */ 462public void 463el_beep(EditLine *el) 464{ 465 466 term_beep(el); 467} 468 469 470/* el_editmode() 471 * Set the state of EDIT_DISABLED from the `edit' command. 472 */ 473protected int 474/*ARGSUSED*/ 475el_editmode(EditLine *el, int argc, char **argv) 476{ 477 const char *how; 478 479 if (argv == NULL || argc != 2 || argv[1] == NULL) 480 return (-1); 481 482 how = argv[1]; 483 if (strcmp(how, "on") == 0) 484 el->el_flags &= ~EDIT_DISABLED; 485 else if (strcmp(how, "off") == 0) 486 el->el_flags |= EDIT_DISABLED; 487 else { 488 (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how); 489 return (-1); 490 } 491 return (0); 492} 493