00001 /* $NetBSD: el.c,v 1.39 2004/07/08 00:51:36 christos Exp $ */ 00002 00003 /*- 00004 * Copyright (c) 1992, 1993 00005 * The Regents of the University of California. All rights reserved. 00006 * 00007 * This code is derived from software contributed to Berkeley by 00008 * Christos Zoulas of Cornell University. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the University nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 */ 00034 00035 #include <config.h> 00036 00037 /* 00038 * el.c: EditLine interface functions 00039 */ 00040 #include <sys/types.h> 00041 #include <sys/param.h> 00042 #include <string.h> 00043 #include <stdlib.h> 00044 #include <stdarg.h> 00045 #include "el.h" 00046 00047 /* el_init(): 00048 * Initialize editline and set default parameters. 00049 */ 00050 public EditLine * 00051 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) 00052 { 00053 00054 EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); 00055 00056 if (el == NULL) 00057 return (NULL); 00058 00059 memset(el, 0, sizeof(EditLine)); 00060 00061 el->el_infd = fileno(fin); 00062 el->el_outfile = fout; 00063 el->el_errfile = ferr; 00064 if ((el->el_prog = el_strdup(prog)) == NULL) { 00065 el_free(el); 00066 return NULL; 00067 } 00068 00069 /* 00070 * Initialize all the modules. Order is important!!! 00071 */ 00072 el->el_flags = 0; 00073 00074 if (term_init(el) == -1) { 00075 el_free(el->el_prog); 00076 el_free(el); 00077 return NULL; 00078 } 00079 (void) key_init(el); 00080 (void) map_init(el); 00081 if (tty_init(el) == -1) 00082 el->el_flags |= NO_TTY; 00083 (void) ch_init(el); 00084 (void) search_init(el); 00085 (void) hist_init(el); 00086 (void) prompt_init(el); 00087 (void) sig_init(el); 00088 (void) read_init(el); 00089 00090 return (el); 00091 } 00092 00093 00094 /* el_end(): 00095 * Clean up. 00096 */ 00097 public void 00098 el_end(EditLine *el) 00099 { 00100 00101 if (el == NULL) 00102 return; 00103 00104 el_reset(el); 00105 00106 term_end(el); 00107 key_end(el); 00108 map_end(el); 00109 tty_end(el); 00110 ch_end(el); 00111 search_end(el); 00112 hist_end(el); 00113 prompt_end(el); 00114 sig_end(el); 00115 00116 el_free((ptr_t) el->el_prog); 00117 el_free((ptr_t) el); 00118 } 00119 00120 00121 /* el_reset(): 00122 * Reset the tty and the parser 00123 */ 00124 public void 00125 el_reset(EditLine *el) 00126 { 00127 00128 tty_cookedmode(el); 00129 ch_reset(el); /* XXX: Do we want that? */ 00130 } 00131 00132 00133 /* el_set(): 00134 * set the editline parameters 00135 */ 00136 public int 00137 el_set(EditLine *el, int op, ...) 00138 { 00139 va_list va; 00140 int rv = 0; 00141 00142 if (el == NULL) 00143 return (-1); 00144 va_start(va, op); 00145 00146 switch (op) { 00147 case EL_PROMPT: 00148 case EL_RPROMPT: 00149 rv = prompt_set(el, va_arg(va, el_pfunc_t), op); 00150 break; 00151 00152 case EL_TERMINAL: 00153 rv = term_set(el, va_arg(va, char *)); 00154 break; 00155 00156 case EL_EDITOR: 00157 rv = map_set_editor(el, va_arg(va, char *)); 00158 break; 00159 00160 case EL_SIGNAL: 00161 if (va_arg(va, int)) 00162 el->el_flags |= HANDLE_SIGNALS; 00163 else 00164 el->el_flags &= ~HANDLE_SIGNALS; 00165 break; 00166 00167 case EL_BIND: 00168 case EL_TELLTC: 00169 case EL_SETTC: 00170 case EL_ECHOTC: 00171 case EL_SETTY: 00172 { 00173 const char *argv[20]; 00174 int i; 00175 00176 for (i = 1; i < 20; i++) 00177 if ((argv[i] = va_arg(va, char *)) == NULL) 00178 break; 00179 00180 switch (op) { 00181 case EL_BIND: 00182 argv[0] = "bind"; 00183 rv = map_bind(el, i, argv); 00184 break; 00185 00186 case EL_TELLTC: 00187 argv[0] = "telltc"; 00188 rv = term_telltc(el, i, argv); 00189 break; 00190 00191 case EL_SETTC: 00192 argv[0] = "settc"; 00193 rv = term_settc(el, i, argv); 00194 break; 00195 00196 case EL_ECHOTC: 00197 argv[0] = "echotc"; 00198 rv = term_echotc(el, i, argv); 00199 break; 00200 00201 case EL_SETTY: 00202 argv[0] = "setty"; 00203 rv = tty_stty(el, i, argv); 00204 break; 00205 00206 default: 00207 rv = -1; 00208 EL_ABORT((el->el_errfile, "Bad op %d\n", op)); 00209 break; 00210 } 00211 break; 00212 } 00213 00214 case EL_ADDFN: 00215 { 00216 char *name = va_arg(va, char *); 00217 char *help = va_arg(va, char *); 00218 el_func_t func = va_arg(va, el_func_t); 00219 00220 rv = map_addfunc(el, name, help, func); 00221 break; 00222 } 00223 00224 case EL_HIST: 00225 { 00226 hist_fun_t func = va_arg(va, hist_fun_t); 00227 ptr_t ptr = va_arg(va, char *); 00228 00229 rv = hist_set(el, func, ptr); 00230 break; 00231 } 00232 00233 case EL_EDITMODE: 00234 if (va_arg(va, int)) 00235 el->el_flags &= ~EDIT_DISABLED; 00236 else 00237 el->el_flags |= EDIT_DISABLED; 00238 rv = 0; 00239 break; 00240 00241 case EL_GETCFN: 00242 { 00243 el_rfunc_t rc = va_arg(va, el_rfunc_t); 00244 rv = el_read_setfn(el, rc); 00245 break; 00246 } 00247 00248 case EL_CLIENTDATA: 00249 el->el_data = va_arg(va, void *); 00250 break; 00251 00252 case EL_UNBUFFERED: 00253 rv = va_arg(va, int); 00254 if (rv && !(el->el_flags & UNBUFFERED)) { 00255 el->el_flags |= UNBUFFERED; 00256 read_prepare(el); 00257 } else if (!rv && (el->el_flags & UNBUFFERED)) { 00258 el->el_flags &= ~UNBUFFERED; 00259 read_finish(el); 00260 } 00261 rv = 0; 00262 break; 00263 00264 case EL_PREP_TERM: 00265 rv = va_arg(va, int); 00266 if (rv) 00267 (void) tty_rawmode(el); 00268 else 00269 (void) tty_cookedmode(el); 00270 rv = 0; 00271 break; 00272 00273 default: 00274 rv = -1; 00275 break; 00276 } 00277 00278 va_end(va); 00279 return (rv); 00280 } 00281 00282 00283 /* el_get(): 00284 * retrieve the editline parameters 00285 */ 00286 public int 00287 el_get(EditLine *el, int op, void *ret) 00288 { 00289 int rv; 00290 00291 if (el == NULL || ret == NULL) 00292 return (-1); 00293 switch (op) { 00294 case EL_PROMPT: 00295 case EL_RPROMPT: 00296 rv = prompt_get(el, (void *) &ret, op); 00297 break; 00298 00299 case EL_EDITOR: 00300 rv = map_get_editor(el, (void *) &ret); 00301 break; 00302 00303 case EL_SIGNAL: 00304 *((int *) ret) = (el->el_flags & HANDLE_SIGNALS); 00305 rv = 0; 00306 break; 00307 00308 case EL_EDITMODE: 00309 *((int *) ret) = (!(el->el_flags & EDIT_DISABLED)); 00310 rv = 0; 00311 break; 00312 00313 case EL_TERMINAL: 00314 term_get(el, (const char **)ret); 00315 rv = 0; 00316 break; 00317 00318 #if 0 /* XXX */ 00319 case EL_BIND: 00320 case EL_TELLTC: 00321 case EL_SETTC: 00322 case EL_ECHOTC: 00323 case EL_SETTY: 00324 { 00325 const char *argv[20]; 00326 int i; 00327 00328 for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) 00329 if ((argv[i] = va_arg(va, char *)) == NULL) 00330 break; 00331 00332 switch (op) { 00333 case EL_BIND: 00334 argv[0] = "bind"; 00335 rv = map_bind(el, i, argv); 00336 break; 00337 00338 case EL_TELLTC: 00339 argv[0] = "telltc"; 00340 rv = term_telltc(el, i, argv); 00341 break; 00342 00343 case EL_SETTC: 00344 argv[0] = "settc"; 00345 rv = term_settc(el, i, argv); 00346 break; 00347 00348 case EL_ECHOTC: 00349 argv[0] = "echotc"; 00350 rv = term_echotc(el, i, argv); 00351 break; 00352 00353 case EL_SETTY: 00354 argv[0] = "setty"; 00355 rv = tty_stty(el, i, argv); 00356 break; 00357 00358 default: 00359 rv = -1; 00360 EL_ABORT((el->errfile, "Bad op %d\n", op)); 00361 break; 00362 } 00363 break; 00364 } 00365 00366 case EL_ADDFN: 00367 { 00368 char *name = va_arg(va, char *); 00369 char *help = va_arg(va, char *); 00370 el_func_t func = va_arg(va, el_func_t); 00371 00372 rv = map_addfunc(el, name, help, func); 00373 break; 00374 } 00375 00376 case EL_HIST: 00377 { 00378 hist_fun_t func = va_arg(va, hist_fun_t); 00379 ptr_t ptr = va_arg(va, char *); 00380 rv = hist_set(el, func, ptr); 00381 } 00382 break; 00383 #endif /* XXX */ 00384 00385 case EL_GETCFN: 00386 *((el_rfunc_t *)ret) = el_read_getfn(el); 00387 rv = 0; 00388 break; 00389 00390 case EL_CLIENTDATA: 00391 *((void **)ret) = el->el_data; 00392 rv = 0; 00393 break; 00394 00395 case EL_UNBUFFERED: 00396 *((int *) ret) = (!(el->el_flags & UNBUFFERED)); 00397 rv = 0; 00398 break; 00399 00400 default: 00401 rv = -1; 00402 } 00403 00404 return (rv); 00405 } 00406 00407 00408 /* el_line(): 00409 * Return editing info 00410 */ 00411 public const LineInfo * 00412 el_line(EditLine *el) 00413 { 00414 00415 return (const LineInfo *) (void *) &el->el_line; 00416 } 00417 00418 00419 /* el_source(): 00420 * Source a file 00421 */ 00422 public int 00423 el_source(EditLine *el, const char *fname) 00424 { 00425 FILE *fp; 00426 size_t len; 00427 char *ptr; 00428 00429 fp = NULL; 00430 if (fname == NULL) { 00431 static const char elpath[] = "/.editrc"; 00432 #ifdef MAXPATHLEN 00433 char path[MAXPATHLEN]; 00434 #else 00435 char path[4096]; 00436 #endif 00437 00438 #ifdef HAVE_ISSETUGID 00439 if (issetugid()) 00440 return (-1); 00441 #endif 00442 if ((ptr = getenv("HOME")) == NULL) 00443 return (-1); 00444 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) 00445 return (-1); 00446 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) 00447 return (-1); 00448 fname = path; 00449 } 00450 if (fp == NULL) 00451 fp = fopen(fname, "r"); 00452 if (fp == NULL) 00453 return (-1); 00454 00455 while ((ptr = fgetln(fp, &len)) != NULL) { 00456 if (len > 0 && ptr[len - 1] == '\n') 00457 --len; 00458 ptr[len] = '\0'; 00459 if (parse_line(el, ptr) == -1) { 00460 (void) fclose(fp); 00461 return (-1); 00462 } 00463 } 00464 00465 (void) fclose(fp); 00466 return (0); 00467 } 00468 00469 00470 /* el_resize(): 00471 * Called from program when terminal is resized 00472 */ 00473 public void 00474 el_resize(EditLine *el) 00475 { 00476 int lins, cols; 00477 sigset_t oset, nset; 00478 00479 (void) sigemptyset(&nset); 00480 (void) sigaddset(&nset, SIGWINCH); 00481 (void) sigprocmask(SIG_BLOCK, &nset, &oset); 00482 00483 /* get the correct window size */ 00484 if (term_get_size(el, &lins, &cols)) 00485 term_change_size(el, lins, cols); 00486 00487 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 00488 } 00489 00490 00491 /* el_beep(): 00492 * Called from the program to beep 00493 */ 00494 public void 00495 el_beep(EditLine *el) 00496 { 00497 00498 term_beep(el); 00499 } 00500 00501 00502 /* el_editmode() 00503 * Set the state of EDIT_DISABLED from the `edit' command. 00504 */ 00505 protected int 00506 /*ARGSUSED*/ 00507 el_editmode(EditLine *el, int argc, const char **argv) 00508 { 00509 const char *how; 00510 00511 if (argv == NULL || argc != 2 || argv[1] == NULL) 00512 return (-1); 00513 00514 how = argv[1]; 00515 if (strcmp(how, "on") == 0) { 00516 el->el_flags &= ~EDIT_DISABLED; 00517 tty_rawmode(el); 00518 } else if (strcmp(how, "off") == 0) { 00519 tty_cookedmode(el); 00520 el->el_flags |= EDIT_DISABLED; 00521 } 00522 else { 00523 (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how); 00524 return (-1); 00525 } 00526 return (0); 00527 }
1.4.7

