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