"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/el.c" (4 Jul 2020, 12489 Bytes) of package /linux/privat/tnftp-20200705.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "el.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 20151004_vs_20200705.

    1 /*  $NetBSD: el.c,v 1.8 2020/07/04 13:43:21 lukem Exp $ */
    2 /*  from    NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp    */
    3 
    4 /*-
    5  * Copyright (c) 1992, 1993
    6  *  The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Christos Zoulas of Cornell University.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 #include "config.h"
   37 
   38 #if 0 /* tnftp */
   39 #if !defined(lint) && !defined(SCCSID)
   40 #if 0
   41 static char sccsid[] = "@(#)el.c    8.2 (Berkeley) 1/3/94";
   42 #else
   43 __RCSID(" NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp  ");
   44 #endif
   45 #endif /* not lint && not SCCSID */
   46 #endif /* tnftp */
   47 
   48 /*
   49  * el.c: EditLine interface functions
   50  */
   51 #if 0 /* tnftp */
   52 #include <sys/types.h>
   53 #include <sys/param.h>
   54 #include <ctype.h>
   55 #include <langinfo.h>
   56 #include <locale.h>
   57 #include <stdarg.h>
   58 #include <stdlib.h>
   59 #include <string.h>
   60 #endif /* tnftp */
   61 
   62 #include "el.h"
   63 #include "parse.h"
   64 #include "read.h"
   65 
   66 /* el_init():
   67  *  Initialize editline and set default parameters.
   68  */
   69 EditLine *
   70 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
   71 {
   72     return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout),
   73     fileno(ferr));
   74 }
   75 
   76 libedit_private EditLine *
   77 el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
   78     int fdin, int fdout, int fderr, int flags)
   79 {
   80     EditLine *el = el_calloc(1, sizeof(*el));
   81 
   82     if (el == NULL)
   83         return NULL;
   84 
   85     el->el_infile = fin;
   86     el->el_outfile = fout;
   87     el->el_errfile = ferr;
   88 
   89     el->el_infd = fdin;
   90     el->el_outfd = fdout;
   91     el->el_errfd = fderr;
   92 
   93     el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch));
   94     if (el->el_prog == NULL) {
   95         el_free(el);
   96         return NULL;
   97     }
   98 
   99     /*
  100          * Initialize all the modules. Order is important!!!
  101          */
  102     el->el_flags = flags;
  103 
  104     if (terminal_init(el) == -1) {
  105         el_free(el->el_prog);
  106         el_free(el);
  107         return NULL;
  108     }
  109     (void) keymacro_init(el);
  110     (void) map_init(el);
  111     if (tty_init(el) == -1)
  112         el->el_flags |= NO_TTY;
  113     (void) ch_init(el);
  114     (void) search_init(el);
  115     (void) hist_init(el);
  116     (void) prompt_init(el);
  117     (void) sig_init(el);
  118     (void) literal_init(el);
  119     if (read_init(el) == -1) {
  120         el_end(el);
  121         return NULL;
  122     }
  123     return el;
  124 }
  125 
  126 EditLine *
  127 el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
  128     int fdin, int fdout, int fderr)
  129 {
  130     return el_init_internal(prog, fin, fout, ferr, fdin, fdout, fderr, 0);
  131 }
  132 
  133 /* el_end():
  134  *  Clean up.
  135  */
  136 void
  137 el_end(EditLine *el)
  138 {
  139 
  140     if (el == NULL)
  141         return;
  142 
  143     el_reset(el);
  144 
  145     terminal_end(el);
  146     keymacro_end(el);
  147     map_end(el);
  148     if (!(el->el_flags & NO_TTY))
  149         tty_end(el, TCSAFLUSH);
  150     ch_end(el);
  151     read_end(el->el_read);
  152     search_end(el);
  153     hist_end(el);
  154     prompt_end(el);
  155     sig_end(el);
  156     literal_end(el);
  157 
  158     el_free(el->el_prog);
  159     el_free(el->el_visual.cbuff);
  160     el_free(el->el_visual.wbuff);
  161     el_free(el->el_scratch.cbuff);
  162     el_free(el->el_scratch.wbuff);
  163     el_free(el->el_lgcyconv.cbuff);
  164     el_free(el->el_lgcyconv.wbuff);
  165     el_free(el);
  166 }
  167 
  168 
  169 /* el_reset():
  170  *  Reset the tty and the parser
  171  */
  172 void
  173 el_reset(EditLine *el)
  174 {
  175 
  176     tty_cookedmode(el);
  177     ch_reset(el);       /* XXX: Do we want that? */
  178 }
  179 
  180 
  181 /* el_set():
  182  *  set the editline parameters
  183  */
  184 int
  185 el_wset(EditLine *el, int op, ...)
  186 {
  187     va_list ap;
  188     int rv = 0;
  189 
  190     if (el == NULL)
  191         return -1;
  192     va_start(ap, op);
  193 
  194     switch (op) {
  195     case EL_PROMPT:
  196     case EL_RPROMPT: {
  197         el_pfunc_t p = va_arg(ap, el_pfunc_t);
  198 
  199         rv = prompt_set(el, p, 0, op, 1);
  200         break;
  201     }
  202 
  203     case EL_RESIZE: {
  204         el_zfunc_t p = va_arg(ap, el_zfunc_t);
  205         void *arg = va_arg(ap, void *);
  206         rv = ch_resizefun(el, p, arg);
  207         break;
  208     }
  209 
  210     case EL_ALIAS_TEXT: {
  211         el_afunc_t p = va_arg(ap, el_afunc_t);
  212         void *arg = va_arg(ap, void *);
  213         rv = ch_aliasfun(el, p, arg);
  214         break;
  215     }
  216 
  217     case EL_PROMPT_ESC:
  218     case EL_RPROMPT_ESC: {
  219         el_pfunc_t p = va_arg(ap, el_pfunc_t);
  220         int c = va_arg(ap, int);
  221 
  222         rv = prompt_set(el, p, (wchar_t)c, op, 1);
  223         break;
  224     }
  225 
  226     case EL_TERMINAL:
  227         rv = terminal_set(el, va_arg(ap, char *));
  228         break;
  229 
  230     case EL_EDITOR:
  231         rv = map_set_editor(el, va_arg(ap, wchar_t *));
  232         break;
  233 
  234     case EL_SIGNAL:
  235         if (va_arg(ap, int))
  236             el->el_flags |= HANDLE_SIGNALS;
  237         else
  238             el->el_flags &= ~HANDLE_SIGNALS;
  239         break;
  240 
  241     case EL_BIND:
  242     case EL_TELLTC:
  243     case EL_SETTC:
  244     case EL_ECHOTC:
  245     case EL_SETTY:
  246     {
  247         const wchar_t *argv[20];
  248         int i;
  249 
  250         for (i = 1; i < (int)__arraycount(argv); i++)
  251             if ((argv[i] = va_arg(ap, wchar_t *)) == NULL)
  252                 break;
  253 
  254         switch (op) {
  255         case EL_BIND:
  256             argv[0] = L"bind";
  257             rv = map_bind(el, i, argv);
  258             break;
  259 
  260         case EL_TELLTC:
  261             argv[0] = L"telltc";
  262             rv = terminal_telltc(el, i, argv);
  263             break;
  264 
  265         case EL_SETTC:
  266             argv[0] = L"settc";
  267             rv = terminal_settc(el, i, argv);
  268             break;
  269 
  270         case EL_ECHOTC:
  271             argv[0] = L"echotc";
  272             rv = terminal_echotc(el, i, argv);
  273             break;
  274 
  275         case EL_SETTY:
  276             argv[0] = L"setty";
  277             rv = tty_stty(el, i, argv);
  278             break;
  279 
  280         default:
  281             rv = -1;
  282             EL_ABORT((el->el_errfile, "Bad op %d\n", op));
  283             break;
  284         }
  285         break;
  286     }
  287 
  288     case EL_ADDFN:
  289     {
  290         wchar_t *name = va_arg(ap, wchar_t *);
  291         wchar_t *help = va_arg(ap, wchar_t *);
  292         el_func_t func = va_arg(ap, el_func_t);
  293 
  294         rv = map_addfunc(el, name, help, func);
  295         break;
  296     }
  297 
  298     case EL_HIST:
  299     {
  300         hist_fun_t func = va_arg(ap, hist_fun_t);
  301         void *ptr = va_arg(ap, void *);
  302 
  303         rv = hist_set(el, func, ptr);
  304         if (MB_CUR_MAX == 1)
  305             el->el_flags &= ~NARROW_HISTORY;
  306         break;
  307     }
  308 
  309     case EL_EDITMODE:
  310         if (va_arg(ap, int))
  311             el->el_flags &= ~EDIT_DISABLED;
  312         else
  313             el->el_flags |= EDIT_DISABLED;
  314         rv = 0;
  315         break;
  316 
  317     case EL_GETCFN:
  318     {
  319         el_rfunc_t rc = va_arg(ap, el_rfunc_t);
  320         rv = el_read_setfn(el->el_read, rc);
  321         break;
  322     }
  323 
  324     case EL_CLIENTDATA:
  325         el->el_data = va_arg(ap, void *);
  326         break;
  327 
  328     case EL_UNBUFFERED:
  329         rv = va_arg(ap, int);
  330         if (rv && !(el->el_flags & UNBUFFERED)) {
  331             el->el_flags |= UNBUFFERED;
  332             read_prepare(el);
  333         } else if (!rv && (el->el_flags & UNBUFFERED)) {
  334             el->el_flags &= ~UNBUFFERED;
  335             read_finish(el);
  336         }
  337         rv = 0;
  338         break;
  339 
  340     case EL_PREP_TERM:
  341         rv = va_arg(ap, int);
  342         if (rv)
  343             (void) tty_rawmode(el);
  344         else
  345             (void) tty_cookedmode(el);
  346         rv = 0;
  347         break;
  348 
  349     case EL_SETFP:
  350     {
  351         FILE *fp;
  352         int what;
  353 
  354         what = va_arg(ap, int);
  355         fp = va_arg(ap, FILE *);
  356 
  357         rv = 0;
  358         switch (what) {
  359         case 0:
  360             el->el_infile = fp;
  361             el->el_infd = fileno(fp);
  362             break;
  363         case 1:
  364             el->el_outfile = fp;
  365             el->el_outfd = fileno(fp);
  366             break;
  367         case 2:
  368             el->el_errfile = fp;
  369             el->el_errfd = fileno(fp);
  370             break;
  371         default:
  372             rv = -1;
  373             break;
  374         }
  375         break;
  376     }
  377 
  378     case EL_REFRESH:
  379         re_clear_display(el);
  380         re_refresh(el);
  381         terminal__flush(el);
  382         break;
  383 
  384     default:
  385         rv = -1;
  386         break;
  387     }
  388 
  389     va_end(ap);
  390     return rv;
  391 }
  392 
  393 
  394 /* el_get():
  395  *  retrieve the editline parameters
  396  */
  397 int
  398 el_wget(EditLine *el, int op, ...)
  399 {
  400     va_list ap;
  401     int rv;
  402 
  403     if (el == NULL)
  404         return -1;
  405 
  406     va_start(ap, op);
  407 
  408     switch (op) {
  409     case EL_PROMPT:
  410     case EL_RPROMPT: {
  411         el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
  412         rv = prompt_get(el, p, 0, op);
  413         break;
  414     }
  415     case EL_PROMPT_ESC:
  416     case EL_RPROMPT_ESC: {
  417         el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
  418         wchar_t *c = va_arg(ap, wchar_t *);
  419 
  420         rv = prompt_get(el, p, c, op);
  421         break;
  422     }
  423 
  424     case EL_EDITOR:
  425         rv = map_get_editor(el, va_arg(ap, const wchar_t **));
  426         break;
  427 
  428     case EL_SIGNAL:
  429         *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
  430         rv = 0;
  431         break;
  432 
  433     case EL_EDITMODE:
  434         *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
  435         rv = 0;
  436         break;
  437 
  438     case EL_TERMINAL:
  439         terminal_get(el, va_arg(ap, const char **));
  440         rv = 0;
  441         break;
  442 
  443     case EL_GETTC:
  444     {
  445         static char name[] = "gettc";
  446         char *argv[3];
  447         argv[0] = name;
  448         argv[1] = va_arg(ap, char *);
  449         argv[2] = va_arg(ap, void *);
  450         rv = terminal_gettc(el, 3, argv);
  451         break;
  452     }
  453 
  454     case EL_GETCFN:
  455         *va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read);
  456         rv = 0;
  457         break;
  458 
  459     case EL_CLIENTDATA:
  460         *va_arg(ap, void **) = el->el_data;
  461         rv = 0;
  462         break;
  463 
  464     case EL_UNBUFFERED:
  465         *va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0;
  466         rv = 0;
  467         break;
  468 
  469     case EL_GETFP:
  470     {
  471         int what;
  472         FILE **fpp;
  473 
  474         what = va_arg(ap, int);
  475         fpp = va_arg(ap, FILE **);
  476         rv = 0;
  477         switch (what) {
  478         case 0:
  479             *fpp = el->el_infile;
  480             break;
  481         case 1:
  482             *fpp = el->el_outfile;
  483             break;
  484         case 2:
  485             *fpp = el->el_errfile;
  486             break;
  487         default:
  488             rv = -1;
  489             break;
  490         }
  491         break;
  492     }
  493     default:
  494         rv = -1;
  495         break;
  496     }
  497     va_end(ap);
  498 
  499     return rv;
  500 }
  501 
  502 
  503 /* el_line():
  504  *  Return editing info
  505  */
  506 const LineInfoW *
  507 el_wline(EditLine *el)
  508 {
  509 
  510     return (const LineInfoW *)(void *)&el->el_line;
  511 }
  512 
  513 
  514 /* el_source():
  515  *  Source a file
  516  */
  517 int
  518 el_source(EditLine *el, const char *fname)
  519 {
  520     FILE *fp;
  521     size_t len;
  522     ssize_t slen;
  523     char *ptr;
  524     char *path = NULL;
  525     const wchar_t *dptr;
  526     int error = 0;
  527 
  528     fp = NULL;
  529     if (fname == NULL) {
  530 #ifdef HAVE_ISSETUGID
  531         if (issetugid())
  532             return -1;
  533 
  534         if ((fname = getenv("EDITRC")) == NULL) {
  535             static const char elpath[] = "/.editrc";
  536             size_t plen = sizeof(elpath);
  537 
  538             if ((ptr = getenv("HOME")) == NULL)
  539                 return -1;
  540             plen += strlen(ptr);
  541             if ((path = el_calloc(plen, sizeof(*path))) == NULL)
  542                 return -1;
  543             (void)snprintf(path, plen, "%s%s", ptr,
  544                 elpath + (*ptr == '\0'));
  545             fname = path;
  546         }
  547 #else
  548         /*
  549          * If issetugid() is missing, always return an error, in order
  550          * to keep from inadvertently opening up the user to a security
  551          * hole.
  552          */
  553         return -1;
  554 #endif
  555     }
  556     if (fname[0] == '\0')
  557         return -1;
  558 
  559     if (fp == NULL)
  560         fp = fopen(fname, "r");
  561     if (fp == NULL) {
  562         el_free(path);
  563         return -1;
  564     }
  565 
  566     ptr = NULL;
  567     len = 0;
  568     while ((slen = getline(&ptr, &len, fp)) != -1) {
  569         if (*ptr == '\n')
  570             continue;   /* Empty line. */
  571         if (slen > 0 && ptr[--slen] == '\n')
  572             ptr[slen] = '\0';
  573 
  574         dptr = ct_decode_string(ptr, &el->el_scratch);
  575         if (!dptr)
  576             continue;
  577         /* loop until first non-space char or EOL */
  578         while (*dptr != '\0' && iswspace(*dptr))
  579             dptr++;
  580         if (*dptr == '#')
  581             continue;   /* ignore, this is a comment line */
  582         if ((error = parse_line(el, dptr)) == -1)
  583             break;
  584     }
  585     free(ptr);
  586 
  587     el_free(path);
  588     (void) fclose(fp);
  589     return error;
  590 }
  591 
  592 
  593 /* el_resize():
  594  *  Called from program when terminal is resized
  595  */
  596 void
  597 el_resize(EditLine *el)
  598 {
  599     int lins, cols;
  600     sigset_t oset, nset;
  601 
  602     (void) sigemptyset(&nset);
  603     (void) sigaddset(&nset, SIGWINCH);
  604     (void) sigprocmask(SIG_BLOCK, &nset, &oset);
  605 
  606     /* get the correct window size */
  607     if (terminal_get_size(el, &lins, &cols))
  608         terminal_change_size(el, lins, cols);
  609 
  610     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
  611 }
  612 
  613 
  614 /* el_beep():
  615  *  Called from the program to beep
  616  */
  617 void
  618 el_beep(EditLine *el)
  619 {
  620 
  621     terminal_beep(el);
  622 }
  623 
  624 
  625 /* el_editmode()
  626  *  Set the state of EDIT_DISABLED from the `edit' command.
  627  */
  628 libedit_private int
  629 /*ARGSUSED*/
  630 el_editmode(EditLine *el, int argc, const wchar_t **argv)
  631 {
  632     const wchar_t *how;
  633 
  634     if (argv == NULL || argc != 2 || argv[1] == NULL)
  635         return -1;
  636 
  637     how = argv[1];
  638     if (wcscmp(how, L"on") == 0) {
  639         el->el_flags &= ~EDIT_DISABLED;
  640         tty_rawmode(el);
  641     } else if (wcscmp(how, L"off") == 0) {
  642         tty_cookedmode(el);
  643         el->el_flags |= EDIT_DISABLED;
  644     }
  645     else {
  646         (void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n",
  647             how);
  648         return -1;
  649     }
  650     return 0;
  651 }