File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / readline / util.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Nov 3 13:35:37 2016 UTC (7 years, 8 months ago) by misho
Branches: readline, MAIN
CVS tags: v6_3p10_cross, v6_3p10, HEAD
readline 6.3p8

    1: /* util.c -- readline utility functions */
    2: 
    3: /* Copyright (C) 1987-2012 Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU Readline Library (Readline), a library
    6:    for reading lines of text with interactive input and history editing.      
    7: 
    8:    Readline is free software: you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation, either version 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    Readline is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License
   19:    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
   20: */
   21: 
   22: #define READLINE_LIBRARY
   23: 
   24: #if defined (HAVE_CONFIG_H)
   25: #  include <config.h>
   26: #endif
   27: 
   28: #include <sys/types.h>
   29: #include <fcntl.h>
   30: #include "posixjmp.h"
   31: 
   32: #if defined (HAVE_UNISTD_H)
   33: #  include <unistd.h>           /* for _POSIX_VERSION */
   34: #endif /* HAVE_UNISTD_H */
   35: 
   36: #if defined (HAVE_STDLIB_H)
   37: #  include <stdlib.h>
   38: #else
   39: #  include "ansi_stdlib.h"
   40: #endif /* HAVE_STDLIB_H */
   41: 
   42: #include <stdio.h>
   43: #include <ctype.h>
   44: 
   45: /* System-specific feature definitions and include files. */
   46: #include "rldefs.h"
   47: #include "rlmbutil.h"
   48: 
   49: #if defined (TIOCSTAT_IN_SYS_IOCTL)
   50: #  include <sys/ioctl.h>
   51: #endif /* TIOCSTAT_IN_SYS_IOCTL */
   52: 
   53: /* Some standard library routines. */
   54: #include "readline.h"
   55: 
   56: #include "rlprivate.h"
   57: #include "xmalloc.h"
   58: 
   59: /* **************************************************************** */
   60: /*								    */
   61: /*			Utility Functions			    */
   62: /*								    */
   63: /* **************************************************************** */
   64: 
   65: /* Return 0 if C is not a member of the class of characters that belong
   66:    in words, or 1 if it is. */
   67: 
   68: int _rl_allow_pathname_alphabetic_chars = 0;
   69: static const char * const pathname_alphabetic_chars = "/-_=~.#$";
   70: 
   71: int
   72: rl_alphabetic (c)
   73:      int c;
   74: {
   75:   if (ALPHABETIC (c))
   76:     return (1);
   77: 
   78:   return (_rl_allow_pathname_alphabetic_chars &&
   79: 	    strchr (pathname_alphabetic_chars, c) != NULL);
   80: }
   81: 
   82: #if defined (HANDLE_MULTIBYTE)
   83: int
   84: _rl_walphabetic (wchar_t wc)
   85: {
   86:   int c;
   87: 
   88:   if (iswalnum (wc))
   89:     return (1);     
   90: 
   91:   c = wc & 0177;
   92:   return (_rl_allow_pathname_alphabetic_chars &&
   93: 	    strchr (pathname_alphabetic_chars, c) != NULL);
   94: }
   95: #endif
   96: 
   97: /* How to abort things. */
   98: int
   99: _rl_abort_internal ()
  100: {
  101:   rl_ding ();
  102:   rl_clear_message ();
  103:   _rl_reset_argument ();
  104:   rl_clear_pending_input ();
  105: 
  106:   RL_UNSETSTATE (RL_STATE_MACRODEF);
  107:   while (rl_executing_macro)
  108:     _rl_pop_executing_macro ();
  109: 
  110:   rl_last_func = (rl_command_func_t *)NULL;
  111: #if defined (HAVE_POSIX_SIGSETJMP)
  112:   siglongjmp (_rl_top_level, 1);
  113: #else
  114:   longjmp (_rl_top_level, 1);
  115: #endif
  116:   return (0);
  117: }
  118: 
  119: int
  120: rl_abort (count, key)
  121:      int count, key;
  122: {
  123:   return (_rl_abort_internal ());
  124: }
  125: 
  126: int
  127: _rl_null_function (count, key)
  128:      int count, key;
  129: {
  130:   return 0;
  131: }
  132: 
  133: int
  134: rl_tty_status (count, key)
  135:      int count, key;
  136: {
  137: #if defined (TIOCSTAT)
  138:   ioctl (1, TIOCSTAT, (char *)0);
  139:   rl_refresh_line (count, key);
  140: #else
  141:   rl_ding ();
  142: #endif
  143:   return 0;
  144: }
  145: 
  146: /* Return a copy of the string between FROM and TO.
  147:    FROM is inclusive, TO is not. */
  148: char *
  149: rl_copy_text (from, to)
  150:      int from, to;
  151: {
  152:   register int length;
  153:   char *copy;
  154: 
  155:   /* Fix it if the caller is confused. */
  156:   if (from > to)
  157:     SWAP (from, to);
  158: 
  159:   length = to - from;
  160:   copy = (char *)xmalloc (1 + length);
  161:   strncpy (copy, rl_line_buffer + from, length);
  162:   copy[length] = '\0';
  163:   return (copy);
  164: }
  165: 
  166: /* Increase the size of RL_LINE_BUFFER until it has enough space to hold
  167:    LEN characters. */
  168: void
  169: rl_extend_line_buffer (len)
  170:      int len;
  171: {
  172:   while (len >= rl_line_buffer_len)
  173:     {
  174:       rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
  175:       rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
  176:     }
  177: 
  178:   _rl_set_the_line ();
  179: }
  180: 
  181: 
  182: /* A function for simple tilde expansion. */
  183: int
  184: rl_tilde_expand (ignore, key)
  185:      int ignore, key;
  186: {
  187:   register int start, end;
  188:   char *homedir, *temp;
  189:   int len;
  190: 
  191:   end = rl_point;
  192:   start = end - 1;
  193: 
  194:   if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
  195:     {
  196:       homedir = tilde_expand ("~");
  197:       _rl_replace_text (homedir, start, end);
  198:       xfree (homedir);
  199:       return (0);
  200:     }
  201:   else if (rl_line_buffer[start] != '~')
  202:     {
  203:       for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
  204:         ;
  205:       start++;
  206:     }
  207: 
  208:   end = start;
  209:   do
  210:     end++;
  211:   while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
  212: 
  213:   if (whitespace (rl_line_buffer[end]) || end >= rl_end)
  214:     end--;
  215: 
  216:   /* If the first character of the current word is a tilde, perform
  217:      tilde expansion and insert the result.  If not a tilde, do
  218:      nothing. */
  219:   if (rl_line_buffer[start] == '~')
  220:     {
  221:       len = end - start + 1;
  222:       temp = (char *)xmalloc (len + 1);
  223:       strncpy (temp, rl_line_buffer + start, len);
  224:       temp[len] = '\0';
  225:       homedir = tilde_expand (temp);
  226:       xfree (temp);
  227: 
  228:       _rl_replace_text (homedir, start, end);
  229:       xfree (homedir);
  230:     }
  231: 
  232:   return (0);
  233: }
  234: 
  235: #if defined (USE_VARARGS)
  236: void
  237: #if defined (PREFER_STDARG)
  238: _rl_ttymsg (const char *format, ...)
  239: #else
  240: _rl_ttymsg (va_alist)
  241:      va_dcl
  242: #endif
  243: {
  244:   va_list args;
  245: #if defined (PREFER_VARARGS)
  246:   char *format;
  247: #endif
  248: 
  249: #if defined (PREFER_STDARG)
  250:   va_start (args, format);
  251: #else
  252:   va_start (args);
  253:   format = va_arg (args, char *);
  254: #endif
  255: 
  256:   fprintf (stderr, "readline: ");
  257:   vfprintf (stderr, format, args);
  258:   fprintf (stderr, "\n");
  259:   fflush (stderr);
  260: 
  261:   va_end (args);
  262: 
  263:   rl_forced_update_display ();
  264: }
  265: 
  266: void
  267: #if defined (PREFER_STDARG)
  268: _rl_errmsg (const char *format, ...)
  269: #else
  270: _rl_errmsg (va_alist)
  271:      va_dcl
  272: #endif
  273: {
  274:   va_list args;
  275: #if defined (PREFER_VARARGS)
  276:   char *format;
  277: #endif
  278: 
  279: #if defined (PREFER_STDARG)
  280:   va_start (args, format);
  281: #else
  282:   va_start (args);
  283:   format = va_arg (args, char *);
  284: #endif
  285: 
  286:   fprintf (stderr, "readline: ");
  287:   vfprintf (stderr, format, args);
  288:   fprintf (stderr, "\n");
  289:   fflush (stderr);
  290: 
  291:   va_end (args);
  292: }
  293: 
  294: #else /* !USE_VARARGS */
  295: void
  296: _rl_ttymsg (format, arg1, arg2)
  297:      char *format;
  298: {
  299:   fprintf (stderr, "readline: ");
  300:   fprintf (stderr, format, arg1, arg2);
  301:   fprintf (stderr, "\n");
  302: 
  303:   rl_forced_update_display ();
  304: }
  305: 
  306: void
  307: _rl_errmsg (format, arg1, arg2)
  308:      char *format;
  309: {
  310:   fprintf (stderr, "readline: ");
  311:   fprintf (stderr, format, arg1, arg2);
  312:   fprintf (stderr, "\n");
  313: }
  314: #endif /* !USE_VARARGS */
  315: 
  316: /* **************************************************************** */
  317: /*								    */
  318: /*			String Utility Functions		    */
  319: /*								    */
  320: /* **************************************************************** */
  321: 
  322: /* Determine if s2 occurs in s1.  If so, return a pointer to the
  323:    match in s1.  The compare is case insensitive. */
  324: char *
  325: _rl_strindex (s1, s2)
  326:      register const char *s1, *s2;
  327: {
  328:   register int i, l, len;
  329: 
  330:   for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
  331:     if (_rl_strnicmp (s1 + i, s2, l) == 0)
  332:       return ((char *) (s1 + i));
  333:   return ((char *)NULL);
  334: }
  335: 
  336: #ifndef HAVE_STRPBRK
  337: /* Find the first occurrence in STRING1 of any character from STRING2.
  338:    Return a pointer to the character in STRING1. */
  339: char *
  340: _rl_strpbrk (string1, string2)
  341:      const char *string1, *string2;
  342: {
  343:   register const char *scan;
  344: #if defined (HANDLE_MULTIBYTE)
  345:   mbstate_t ps;
  346:   register int i, v;
  347: 
  348:   memset (&ps, 0, sizeof (mbstate_t));
  349: #endif
  350: 
  351:   for (; *string1; string1++)
  352:     {
  353:       for (scan = string2; *scan; scan++)
  354: 	{
  355: 	  if (*string1 == *scan)
  356: 	    return ((char *)string1);
  357: 	}
  358: #if defined (HANDLE_MULTIBYTE)
  359:       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
  360: 	{
  361: 	  v = _rl_get_char_len (string1, &ps);
  362: 	  if (v > 1)
  363: 	    string1 += v - 1;	/* -1 to account for auto-increment in loop */
  364: 	}
  365: #endif
  366:     }
  367:   return ((char *)NULL);
  368: }
  369: #endif
  370: 
  371: #if !defined (HAVE_STRCASECMP)
  372: /* Compare at most COUNT characters from string1 to string2.  Case
  373:    doesn't matter (strncasecmp). */
  374: int
  375: _rl_strnicmp (string1, string2, count)
  376:      const char *string1;
  377:      const char *string2;
  378:      int count;
  379: {
  380:   register const char *s1;
  381:   register const char *s2;
  382:   register int d;
  383: 
  384:   if (count <= 0 || (string1 == string2))
  385:     return 0;
  386: 
  387:   s1 = string1;
  388:   s2 = string2;
  389:   do
  390:     {
  391:       d = _rl_to_lower (*s1) - _rl_to_lower (*s2);	/* XXX - cast to unsigned char? */
  392:       if (d != 0)
  393: 	return d;
  394:       if (*s1++ == '\0')
  395:         break;
  396:       s2++;
  397:     }
  398:   while (--count != 0);
  399: 
  400:   return (0);
  401: }
  402: 
  403: /* strcmp (), but caseless (strcasecmp). */
  404: int
  405: _rl_stricmp (string1, string2)
  406:      const char *string1;
  407:      const char *string2;
  408: {
  409:   register const char *s1;
  410:   register const char *s2;
  411:   register int d;
  412: 
  413:   s1 = string1;
  414:   s2 = string2;
  415: 
  416:   if (s1 == s2)
  417:     return 0;
  418: 
  419:   while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0)
  420:     {
  421:       if (*s1++ == '\0')
  422:         return 0;
  423:       s2++;
  424:     }
  425: 
  426:   return (d);
  427: }
  428: #endif /* !HAVE_STRCASECMP */
  429: 
  430: /* Stupid comparison routine for qsort () ing strings. */
  431: int
  432: _rl_qsort_string_compare (s1, s2)
  433:   char **s1, **s2;
  434: {
  435: #if defined (HAVE_STRCOLL)
  436:   return (strcoll (*s1, *s2));
  437: #else
  438:   int result;
  439: 
  440:   result = **s1 - **s2;
  441:   if (result == 0)
  442:     result = strcmp (*s1, *s2);
  443: 
  444:   return result;
  445: #endif
  446: }
  447: 
  448: /* Function equivalents for the macros defined in chardefs.h. */
  449: #define FUNCTION_FOR_MACRO(f)	int (f) (c) int c; { return f (c); }
  450: 
  451: FUNCTION_FOR_MACRO (_rl_digit_p)
  452: FUNCTION_FOR_MACRO (_rl_digit_value)
  453: FUNCTION_FOR_MACRO (_rl_lowercase_p)
  454: FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
  455: FUNCTION_FOR_MACRO (_rl_to_lower)
  456: FUNCTION_FOR_MACRO (_rl_to_upper)
  457: FUNCTION_FOR_MACRO (_rl_uppercase_p)
  458: 
  459: /* A convenience function, to force memory deallocation to be performed
  460:    by readline.  DLLs on Windows apparently require this. */
  461: void
  462: rl_free (mem)
  463:      void *mem;
  464: {
  465:   if (mem)
  466:     free (mem);
  467: }
  468: 
  469: /* Backwards compatibility, now that savestring has been removed from
  470:    all `public' readline header files. */
  471: #undef _rl_savestring
  472: char *
  473: _rl_savestring (s)
  474:      const char *s;
  475: {
  476:   return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
  477: }
  478: 
  479: #if defined (DEBUG)
  480: #if defined (USE_VARARGS)
  481: static FILE *_rl_tracefp;
  482: 
  483: void
  484: #if defined (PREFER_STDARG)
  485: _rl_trace (const char *format, ...)
  486: #else
  487: _rl_trace (va_alist)
  488:      va_dcl
  489: #endif
  490: {
  491:   va_list args;
  492: #if defined (PREFER_VARARGS)
  493:   char *format;
  494: #endif
  495: 
  496: #if defined (PREFER_STDARG)
  497:   va_start (args, format);
  498: #else
  499:   va_start (args);
  500:   format = va_arg (args, char *);
  501: #endif
  502: 
  503:   if (_rl_tracefp == 0)
  504:     _rl_tropen ();
  505:   vfprintf (_rl_tracefp, format, args);
  506:   fprintf (_rl_tracefp, "\n");
  507:   fflush (_rl_tracefp);
  508: 
  509:   va_end (args);
  510: }
  511: 
  512: int
  513: _rl_tropen ()
  514: {
  515:   char fnbuf[128];
  516: 
  517:   if (_rl_tracefp)
  518:     fclose (_rl_tracefp);
  519:   sprintf (fnbuf, "/var/tmp/rltrace.%ld", (long)getpid());
  520:   unlink(fnbuf);
  521:   _rl_tracefp = fopen (fnbuf, "w+");
  522:   return _rl_tracefp != 0;
  523: }
  524: 
  525: int
  526: _rl_trclose ()
  527: {
  528:   int r;
  529: 
  530:   r = fclose (_rl_tracefp);
  531:   _rl_tracefp = 0;
  532:   return r;
  533: }
  534: 
  535: void
  536: _rl_settracefp (fp)
  537:      FILE *fp;
  538: {
  539:   _rl_tracefp = fp;
  540: }
  541: #endif
  542: #endif /* DEBUG */
  543: 
  544: 
  545: #if HAVE_DECL_AUDIT_USER_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
  546: #include <sys/socket.h>
  547: #include <linux/audit.h>
  548: #include <linux/netlink.h>
  549: 
  550: /* Report STRING to the audit system. */
  551: void
  552: _rl_audit_tty (string)
  553:      char *string;
  554: {
  555:   struct sockaddr_nl addr;
  556:   struct msghdr msg;
  557:   struct nlmsghdr nlm;
  558:   struct iovec iov[2];
  559:   size_t size;
  560:   int fd;
  561: 
  562:   fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
  563:   if (fd < 0)
  564:     return;
  565:   size = strlen (string) + 1;
  566: 
  567:   nlm.nlmsg_len = NLMSG_LENGTH (size);
  568:   nlm.nlmsg_type = AUDIT_USER_TTY;
  569:   nlm.nlmsg_flags = NLM_F_REQUEST;
  570:   nlm.nlmsg_seq = 0;
  571:   nlm.nlmsg_pid = 0;
  572: 
  573:   iov[0].iov_base = &nlm;
  574:   iov[0].iov_len = sizeof (nlm);
  575:   iov[1].iov_base = string;
  576:   iov[1].iov_len = size;
  577: 
  578:   addr.nl_family = AF_NETLINK;
  579:   addr.nl_pid = 0;
  580:   addr.nl_groups = 0;
  581: 
  582:   msg.msg_name = &addr;
  583:   msg.msg_namelen = sizeof (addr);
  584:   msg.msg_iov = iov;
  585:   msg.msg_iovlen = 2;
  586:   msg.msg_control = NULL;
  587:   msg.msg_controllen = 0;
  588:   msg.msg_flags = 0;
  589: 
  590:   (void)sendmsg (fd, &msg, 0);
  591:   close (fd);
  592: }
  593: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>