el.c revision 84201
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 37#include <sys/cdefs.h> 38__FBSDID("$FreeBSD: head/lib/libedit/el.c 84201 2001-09-30 21:21:36Z dillon $"); 39#if !defined(lint) && !defined(SCCSID) 40#if 0 41static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; 42#endif 43#endif /* not lint && not SCCSID */ 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 <errno.h> 53#include <string.h> 54#include <stdlib.h> 55#if __STDC__ 56# include <stdarg.h> 57#else 58# include <varargs.h> 59#endif 60#include "el.h" 61 62/* el_init(): 63 * Initialize editline and set default parameters. 64 */ 65public EditLine * 66el_init(prog, fin, fout) 67 const char *prog; 68 FILE *fin, *fout; 69{ 70 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); 71#ifdef DEBUG 72 char *tty; 73#endif 74 75 if (el == NULL) 76 return NULL; 77 78 memset(el, 0, sizeof(EditLine)); 79 80 el->el_infd = fileno(fin); 81 el->el_outfile = fout; 82 el->el_prog = strdup(prog); 83 84#ifdef DEBUG 85 if (issetugid() == 0 && (tty = getenv("DEBUGTTY")) != NULL) { 86 el->el_errfile = fopen(tty, "w"); 87 if (el->el_errfile == NULL) { 88 (void) fprintf(stderr, "Cannot open %s (%s).\n", 89 tty, strerror(errno)); 90 return NULL; 91 } 92 } 93 else 94#endif 95 el->el_errfile = stderr; 96 97 /* 98 * Initialize all the modules. Order is important!!! 99 */ 100 (void) term_init(el); 101 (void) tty_init(el); 102 (void) key_init(el); 103 (void) map_init(el); 104 (void) ch_init(el); 105 (void) search_init(el); 106 (void) hist_init(el); 107 (void) prompt_init(el); 108 (void) sig_init(el); 109 el->el_flags = 0; 110 el->data = NULL; 111 112 return el; 113} /* end el_init */ 114 115 116/* el_end(): 117 * Clean up. 118 */ 119public void 120el_end(el) 121 EditLine *el; 122{ 123 if (el == NULL) 124 return; 125 126 el_reset(el); 127 128 term_end(el); 129 tty_end(el); 130 key_end(el); 131 map_end(el); 132 ch_end(el); 133 search_end(el); 134 hist_end(el); 135 prompt_end(el); 136 sig_end(el); 137 138 el_free((ptr_t) el->el_prog); 139 el_free((ptr_t) el); 140} /* end el_end */ 141 142 143/* el_reset(): 144 * Reset the tty and the parser 145 */ 146public void 147el_reset(el) 148 EditLine *el; 149{ 150 tty_cookedmode(el); 151 ch_reset(el); /* XXX: Do we want that? */ 152} 153 154 155/* el_set(): 156 * set the editline parameters 157 */ 158public int 159#if __STDC__ 160el_set(EditLine *el, int op, ...) 161#else 162el_set(va_alist) 163 va_dcl 164#endif 165{ 166 va_list va; 167 int rv; 168#if __STDC__ 169 va_start(va, op); 170#else 171 EditLine *el; 172 int op; 173 174 va_start(va); 175 el = va_arg(va, EditLine *); 176 op = va_arg(va, int); 177#endif 178 179 switch (op) { 180 case EL_PROMPT: 181 rv = prompt_set(el, va_arg(va, el_pfunc_t)); 182 break; 183 184 case EL_TERMINAL: 185 rv = term_set(el, va_arg(va, char *)); 186 break; 187 188 case EL_EDITOR: 189 rv = map_set_editor(el, va_arg(va, char *)); 190 break; 191 192 case EL_SIGNAL: 193 if (va_arg(va, int)) 194 el->el_flags |= HANDLE_SIGNALS; 195 else 196 el->el_flags &= ~HANDLE_SIGNALS; 197 rv = 0; 198 break; 199 200 case EL_BIND: 201 case EL_TELLTC: 202 case EL_SETTC: 203 case EL_ECHOTC: 204 case EL_SETTY: 205 { 206 char *argv[20]; 207 int i; 208 for (i = 1; i < 20; i++) 209 if ((argv[i] = va_arg(va, char *)) == NULL) 210 break; 211 212 switch (op) { 213 case EL_BIND: 214 argv[0] = "bind"; 215 rv = map_bind(el, i, argv); 216 break; 217 218 case EL_TELLTC: 219 argv[0] = "telltc"; 220 rv = term_telltc(el, i, argv); 221 break; 222 223 case EL_SETTC: 224 argv[0] = "settc"; 225 rv = term_settc(el, i, argv); 226 break; 227 228 case EL_ECHOTC: 229 argv[0] = "echotc"; 230 rv = term_echotc(el, i, argv); 231 break; 232 233 case EL_SETTY: 234 argv[0] = "setty"; 235 rv = tty_stty(el, i, argv); 236 break; 237 238 default: 239 rv = -1; 240 abort(); 241 break; 242 } 243 } 244 break; 245 246 case EL_ADDFN: 247 { 248 char *name = va_arg(va, char *); 249 char *help = va_arg(va, char *); 250 el_func_t func = va_arg(va, el_func_t); 251 rv = map_addfunc(el, name, help, func); 252 } 253 break; 254 255 case EL_HIST: 256 { 257 hist_fun_t func = va_arg(va, hist_fun_t); 258 ptr_t ptr = va_arg(va, char *); 259 rv = hist_set(el, func, ptr); 260 } 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_line(): 273 * Return editing info 274 */ 275public const LineInfo * 276el_line(el) 277 EditLine *el; 278{ 279 return (const LineInfo *) &el->el_line; 280} 281 282static const char elpath[] = "/.editrc"; 283 284/* el_source(): 285 * Source a file 286 */ 287public int 288el_source(el, fname) 289 EditLine *el; 290 const char *fname; 291{ 292 FILE *fp; 293 size_t len; 294 char *ptr, path[MAXPATHLEN]; 295 296 if (fname == NULL) { 297 if (issetugid() != 0 || (ptr = getenv("HOME")) == NULL) 298 return -1; 299 (void) snprintf(path, sizeof(path), "%s%s", ptr, elpath); 300 fname = path; 301 } 302 303 if ((fp = fopen(fname, "r")) == NULL) 304 return -1; 305 306 while ((ptr = fgetln(fp, &len)) != NULL) { 307 if (ptr[len - 1] == '\n') 308 --len; 309 ptr[len] = '\0'; 310 311 if (parse_line(el, ptr) == -1) { 312 (void) fclose(fp); 313 return -1; 314 } 315 } 316 317 (void) fclose(fp); 318 return 0; 319} 320 321 322/* el_resize(): 323 * Called from program when terminal is resized 324 */ 325public void 326el_resize(el) 327 EditLine *el; 328{ 329 int lins, cols; 330 sigset_t oset, nset; 331 (void) sigemptyset(&nset); 332 (void) sigaddset(&nset, SIGWINCH); 333 (void) sigprocmask(SIG_BLOCK, &nset, &oset); 334 335 /* get the correct window size */ 336 if (term_get_size(el, &lins, &cols)) 337 term_change_size(el, lins, cols); 338 339 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 340} 341 342public void 343el_data_set (el, data) 344 EditLine *el; 345 void *data; 346{ 347 el->data = data; 348 349 return; 350} 351 352public void * 353el_data_get (el) 354 EditLine *el; 355{ 356 if (el->data) 357 return (el->data); 358 return (NULL); 359} 360