LCOV - code coverage report
Current view: top level - src/bin/psql - input.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 24 134 17.9 %
Date: 2017-09-29 13:40:31 Functions: 2 10 20.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * psql - the PostgreSQL interactive terminal
       3             :  *
       4             :  * Copyright (c) 2000-2017, PostgreSQL Global Development Group
       5             :  *
       6             :  * src/bin/psql/input.c
       7             :  */
       8             : #include "postgres_fe.h"
       9             : 
      10             : #ifndef WIN32
      11             : #include <unistd.h>
      12             : #endif
      13             : #include <fcntl.h>
      14             : #include <limits.h>
      15             : 
      16             : #include "input.h"
      17             : #include "settings.h"
      18             : #include "tab-complete.h"
      19             : #include "common.h"
      20             : 
      21             : #ifndef WIN32
      22             : #define PSQLHISTORY ".psql_history"
      23             : #else
      24             : #define PSQLHISTORY "psql_history"
      25             : #endif
      26             : 
      27             : /* Runtime options for turning off readline and history */
      28             : /* (of course there is no runtime command for doing that :) */
      29             : #ifdef USE_READLINE
      30             : static bool useReadline;
      31             : static bool useHistory;
      32             : 
      33             : static char *psql_history;
      34             : 
      35             : static int  history_lines_added;
      36             : 
      37             : 
      38             : /*
      39             :  *  Preserve newlines in saved queries by mapping '\n' to NL_IN_HISTORY
      40             :  *
      41             :  *  It is assumed NL_IN_HISTORY will never be entered by the user
      42             :  *  nor appear inside a multi-byte string.  0x00 is not properly
      43             :  *  handled by the readline routines so it can not be used
      44             :  *  for this purpose.
      45             :  */
      46             : #define NL_IN_HISTORY   0x01
      47             : #endif
      48             : 
      49             : static void finishInput(void);
      50             : 
      51             : 
      52             : /*
      53             :  * gets_interactive()
      54             :  *
      55             :  * Gets a line of interactive input, using readline if desired.
      56             :  *
      57             :  * prompt: the prompt string to be used
      58             :  * query_buf: buffer containing lines already read in the current command
      59             :  * (query_buf is not modified here, but may be consulted for tab completion)
      60             :  *
      61             :  * The result is a malloc'd string.
      62             :  *
      63             :  * Caller *must* have set up sigint_interrupt_jmp before calling.
      64             :  */
      65             : char *
      66           0 : gets_interactive(const char *prompt, PQExpBuffer query_buf)
      67             : {
      68             : #ifdef USE_READLINE
      69           0 :     if (useReadline)
      70             :     {
      71             :         char       *result;
      72             : 
      73             :         /*
      74             :          * Some versions of readline don't notice SIGWINCH signals that arrive
      75             :          * when not actively reading input.  The simplest fix is to always
      76             :          * re-read the terminal size.  This leaves a window for SIGWINCH to be
      77             :          * missed between here and where readline() enables libreadline's
      78             :          * signal handler, but that's probably short enough to be ignored.
      79             :          */
      80             : #ifdef HAVE_RL_RESET_SCREEN_SIZE
      81           0 :         rl_reset_screen_size();
      82             : #endif
      83             : 
      84             :         /* Make current query_buf available to tab completion callback */
      85           0 :         tab_completion_query_buf = query_buf;
      86             : 
      87             :         /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
      88           0 :         sigint_interrupt_enabled = true;
      89             : 
      90             :         /* On some platforms, readline is declared as readline(char *) */
      91           0 :         result = readline((char *) prompt);
      92             : 
      93             :         /* Disable SIGINT again */
      94           0 :         sigint_interrupt_enabled = false;
      95             : 
      96             :         /* Pure neatnik-ism */
      97           0 :         tab_completion_query_buf = NULL;
      98             : 
      99           0 :         return result;
     100             :     }
     101             : #endif
     102             : 
     103           0 :     fputs(prompt, stdout);
     104           0 :     fflush(stdout);
     105           0 :     return gets_fromFile(stdin);
     106             : }
     107             : 
     108             : 
     109             : /*
     110             :  * Append the line to the history buffer, making sure there is a trailing '\n'
     111             :  */
     112             : void
     113           0 : pg_append_history(const char *s, PQExpBuffer history_buf)
     114             : {
     115             : #ifdef USE_READLINE
     116           0 :     if (useHistory && s)
     117             :     {
     118           0 :         appendPQExpBufferStr(history_buf, s);
     119           0 :         if (!s[0] || s[strlen(s) - 1] != '\n')
     120           0 :             appendPQExpBufferChar(history_buf, '\n');
     121             :     }
     122             : #endif
     123           0 : }
     124             : 
     125             : 
     126             : /*
     127             :  * Emit accumulated history entry to readline's history mechanism,
     128             :  * then reset the buffer to empty.
     129             :  *
     130             :  * Note: we write nothing if history_buf is empty, so extra calls to this
     131             :  * function don't hurt.  There must have been at least one line added by
     132             :  * pg_append_history before we'll do anything.
     133             :  */
     134             : void
     135          12 : pg_send_history(PQExpBuffer history_buf)
     136             : {
     137             : #ifdef USE_READLINE
     138             :     static char *prev_hist = NULL;
     139             : 
     140          12 :     char       *s = history_buf->data;
     141             :     int         i;
     142             : 
     143             :     /* Trim any trailing \n's (OK to scribble on history_buf) */
     144          12 :     for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
     145             :         ;
     146          12 :     s[i + 1] = '\0';
     147             : 
     148          12 :     if (useHistory && s[0])
     149             :     {
     150           0 :         if (((pset.histcontrol & hctl_ignorespace) &&
     151           0 :              s[0] == ' ') ||
     152           0 :             ((pset.histcontrol & hctl_ignoredups) &&
     153           0 :              prev_hist && strcmp(s, prev_hist) == 0))
     154             :         {
     155             :             /* Ignore this line as far as history is concerned */
     156             :         }
     157             :         else
     158             :         {
     159             :             /* Save each previous line for ignoredups processing */
     160           0 :             if (prev_hist)
     161           0 :                 free(prev_hist);
     162           0 :             prev_hist = pg_strdup(s);
     163             :             /* And send it to readline */
     164           0 :             add_history(s);
     165             :             /* Count lines added to history for use later */
     166           0 :             history_lines_added++;
     167             :         }
     168             :     }
     169             : 
     170          12 :     resetPQExpBuffer(history_buf);
     171             : #endif
     172          12 : }
     173             : 
     174             : 
     175             : /*
     176             :  * gets_fromFile
     177             :  *
     178             :  * Gets a line of noninteractive input from a file (which could be stdin).
     179             :  * The result is a malloc'd string, or NULL on EOF or input error.
     180             :  *
     181             :  * Caller *must* have set up sigint_interrupt_jmp before calling.
     182             :  *
     183             :  * Note: we re-use a static PQExpBuffer for each call.  This is to avoid
     184             :  * leaking memory if interrupted by SIGINT.
     185             :  */
     186             : char *
     187       58507 : gets_fromFile(FILE *source)
     188             : {
     189             :     static PQExpBuffer buffer = NULL;
     190             : 
     191             :     char        line[1024];
     192             : 
     193       58507 :     if (buffer == NULL)         /* first time through? */
     194         180 :         buffer = createPQExpBuffer();
     195             :     else
     196       58327 :         resetPQExpBuffer(buffer);
     197             : 
     198             :     for (;;)
     199             :     {
     200             :         char       *result;
     201             : 
     202             :         /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
     203       58507 :         sigint_interrupt_enabled = true;
     204             : 
     205             :         /* Get some data */
     206       58507 :         result = fgets(line, sizeof(line), source);
     207             : 
     208             :         /* Disable SIGINT again */
     209       58507 :         sigint_interrupt_enabled = false;
     210             : 
     211             :         /* EOF or error? */
     212       58507 :         if (result == NULL)
     213             :         {
     214         180 :             if (ferror(source))
     215             :             {
     216           0 :                 psql_error("could not read from input file: %s\n",
     217           0 :                            strerror(errno));
     218           0 :                 return NULL;
     219             :             }
     220         180 :             break;
     221             :         }
     222             : 
     223       58327 :         appendPQExpBufferStr(buffer, line);
     224             : 
     225       58327 :         if (PQExpBufferBroken(buffer))
     226             :         {
     227           0 :             psql_error("out of memory\n");
     228           0 :             return NULL;
     229             :         }
     230             : 
     231             :         /* EOL? */
     232       58327 :         if (buffer->len > 0 && buffer->data[buffer->len - 1] == '\n')
     233             :         {
     234       58327 :             buffer->data[buffer->len - 1] = '\0';
     235       58327 :             return pg_strdup(buffer->data);
     236             :         }
     237           0 :     }
     238             : 
     239         180 :     if (buffer->len > 0)      /* EOF after reading some bufferload(s) */
     240           0 :         return pg_strdup(buffer->data);
     241             : 
     242             :     /* EOF, so return null */
     243         180 :     return NULL;
     244             : }
     245             : 
     246             : 
     247             : #ifdef USE_READLINE
     248             : 
     249             : /*
     250             :  * Macros to iterate over each element of the history list in order
     251             :  *
     252             :  * You would think this would be simple enough, but in its inimitable fashion
     253             :  * libedit has managed to break it: in libreadline we must use next_history()
     254             :  * to go from oldest to newest, but in libedit we must use previous_history().
     255             :  * To detect what to do, we make a trial call of previous_history(): if it
     256             :  * fails, then either next_history() is what to use, or there's zero or one
     257             :  * history entry so that it doesn't matter which direction we go.
     258             :  *
     259             :  * In case that wasn't disgusting enough: the code below is not as obvious as
     260             :  * it might appear.  In some libedit releases history_set_pos(0) fails until
     261             :  * at least one add_history() call has been done.  This is not an issue for
     262             :  * printHistory() or encode_history(), which cannot be invoked before that has
     263             :  * happened.  In decode_history(), that's not so, and what actually happens is
     264             :  * that we are sitting on the newest entry to start with, previous_history()
     265             :  * fails, and we iterate over all the entries using next_history().  So the
     266             :  * decode_history() loop iterates over the entries in the wrong order when
     267             :  * using such a libedit release, and if there were another attempt to use
     268             :  * BEGIN_ITERATE_HISTORY() before some add_history() call had happened, it
     269             :  * wouldn't work.  Fortunately we don't care about either of those things.
     270             :  *
     271             :  * Usage pattern is:
     272             :  *
     273             :  *      BEGIN_ITERATE_HISTORY(varname);
     274             :  *      {
     275             :  *          loop body referencing varname->line;
     276             :  *      }
     277             :  *      END_ITERATE_HISTORY();
     278             :  */
     279             : #define BEGIN_ITERATE_HISTORY(VARNAME) \
     280             :     do { \
     281             :         HIST_ENTRY *VARNAME; \
     282             :         bool        use_prev_; \
     283             :         \
     284             :         history_set_pos(0); \
     285             :         use_prev_ = (previous_history() != NULL); \
     286             :         history_set_pos(0); \
     287             :         for (VARNAME = current_history(); VARNAME != NULL; \
     288             :              VARNAME = use_prev_ ? previous_history() : next_history()) \
     289             :         { \
     290             :             (void) 0
     291             : 
     292             : #define END_ITERATE_HISTORY() \
     293             :         } \
     294             :     } while(0)
     295             : 
     296             : 
     297             : /*
     298             :  * Convert newlines to NL_IN_HISTORY for safe saving in readline history file
     299             :  */
     300             : static void
     301           0 : encode_history(void)
     302             : {
     303           0 :     BEGIN_ITERATE_HISTORY(cur_hist);
     304             :     {
     305             :         char       *cur_ptr;
     306             : 
     307             :         /* some platforms declare HIST_ENTRY.line as const char * */
     308           0 :         for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
     309             :         {
     310           0 :             if (*cur_ptr == '\n')
     311           0 :                 *cur_ptr = NL_IN_HISTORY;
     312             :         }
     313             :     }
     314             :     END_ITERATE_HISTORY();
     315           0 : }
     316             : 
     317             : /*
     318             :  * Reverse the above encoding
     319             :  */
     320             : static void
     321           0 : decode_history(void)
     322             : {
     323           0 :     BEGIN_ITERATE_HISTORY(cur_hist);
     324             :     {
     325             :         char       *cur_ptr;
     326             : 
     327             :         /* some platforms declare HIST_ENTRY.line as const char * */
     328           0 :         for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
     329             :         {
     330           0 :             if (*cur_ptr == NL_IN_HISTORY)
     331           0 :                 *cur_ptr = '\n';
     332             :         }
     333             :     }
     334             :     END_ITERATE_HISTORY();
     335           0 : }
     336             : #endif                          /* USE_READLINE */
     337             : 
     338             : 
     339             : /*
     340             :  * Put any startup stuff related to input in here. It's good to maintain
     341             :  * abstraction this way.
     342             :  *
     343             :  * The only "flag" right now is 1 for use readline & history.
     344             :  */
     345             : void
     346           0 : initializeInput(int flags)
     347             : {
     348             : #ifdef USE_READLINE
     349           0 :     if (flags & 1)
     350             :     {
     351             :         const char *histfile;
     352             :         char        home[MAXPGPATH];
     353             : 
     354           0 :         useReadline = true;
     355             : 
     356             :         /* these two things must be done in this order: */
     357           0 :         initialize_readline();
     358           0 :         rl_initialize();
     359             : 
     360           0 :         useHistory = true;
     361           0 :         using_history();
     362           0 :         history_lines_added = 0;
     363             : 
     364           0 :         histfile = GetVariable(pset.vars, "HISTFILE");
     365             : 
     366           0 :         if (histfile == NULL)
     367             :         {
     368             :             char       *envhist;
     369             : 
     370           0 :             envhist = getenv("PSQL_HISTORY");
     371           0 :             if (envhist != NULL && strlen(envhist) > 0)
     372           0 :                 histfile = envhist;
     373             :         }
     374             : 
     375           0 :         if (histfile == NULL)
     376             :         {
     377           0 :             if (get_home_path(home))
     378           0 :                 psql_history = psprintf("%s/%s", home, PSQLHISTORY);
     379             :         }
     380             :         else
     381             :         {
     382           0 :             psql_history = pg_strdup(histfile);
     383           0 :             expand_tilde(&psql_history);
     384             :         }
     385             : 
     386           0 :         if (psql_history)
     387             :         {
     388           0 :             read_history(psql_history);
     389           0 :             decode_history();
     390             :         }
     391             :     }
     392             : #endif
     393             : 
     394           0 :     atexit(finishInput);
     395           0 : }
     396             : 
     397             : 
     398             : /*
     399             :  * This function saves the readline history when psql exits.
     400             :  *
     401             :  * fname: pathname of history file.  (Should really be "const char *",
     402             :  * but some ancient versions of readline omit the const-decoration.)
     403             :  *
     404             :  * max_lines: if >= 0, limit history file to that many entries.
     405             :  */
     406             : #ifdef USE_READLINE
     407             : static bool
     408           0 : saveHistory(char *fname, int max_lines)
     409             : {
     410             :     int         errnum;
     411             : 
     412             :     /*
     413             :      * Suppressing the write attempt when HISTFILE is set to /dev/null may
     414             :      * look like a negligible optimization, but it's necessary on e.g. macOS,
     415             :      * where write_history will fail because it tries to chmod the target
     416             :      * file.
     417             :      */
     418           0 :     if (strcmp(fname, DEVNULL) != 0)
     419             :     {
     420             :         /*
     421             :          * Encode \n, since otherwise readline will reload multiline history
     422             :          * entries as separate lines.  (libedit doesn't really need this, but
     423             :          * we do it anyway since it's too hard to tell which implementation we
     424             :          * are using.)
     425             :          */
     426           0 :         encode_history();
     427             : 
     428             :         /*
     429             :          * On newer versions of libreadline, truncate the history file as
     430             :          * needed and then append what we've added.  This avoids overwriting
     431             :          * history from other concurrent sessions (although there are still
     432             :          * race conditions when two sessions exit at about the same time). If
     433             :          * we don't have those functions, fall back to write_history().
     434             :          */
     435             : #if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
     436             :         {
     437             :             int         nlines;
     438             :             int         fd;
     439             : 
     440             :             /* truncate previous entries if needed */
     441           0 :             if (max_lines >= 0)
     442             :             {
     443           0 :                 nlines = Max(max_lines - history_lines_added, 0);
     444           0 :                 (void) history_truncate_file(fname, nlines);
     445             :             }
     446             :             /* append_history fails if file doesn't already exist :-( */
     447           0 :             fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
     448           0 :             if (fd >= 0)
     449           0 :                 close(fd);
     450             :             /* append the appropriate number of lines */
     451           0 :             if (max_lines >= 0)
     452           0 :                 nlines = Min(max_lines, history_lines_added);
     453             :             else
     454           0 :                 nlines = history_lines_added;
     455           0 :             errnum = append_history(nlines, fname);
     456           0 :             if (errnum == 0)
     457           0 :                 return true;
     458             :         }
     459             : #else                           /* don't have append support */
     460             :         {
     461             :             /* truncate what we have ... */
     462             :             if (max_lines >= 0)
     463             :                 stifle_history(max_lines);
     464             :             /* ... and overwrite file.  Tough luck for concurrent sessions. */
     465             :             errnum = write_history(fname);
     466             :             if (errnum == 0)
     467             :                 return true;
     468             :         }
     469             : #endif
     470             : 
     471           0 :         psql_error("could not save history to file \"%s\": %s\n",
     472             :                    fname, strerror(errnum));
     473             :     }
     474           0 :     return false;
     475             : }
     476             : #endif
     477             : 
     478             : 
     479             : 
     480             : /*
     481             :  * Print history to the specified file, or to the console if fname is NULL
     482             :  * (psql \s command)
     483             :  *
     484             :  * We used to use saveHistory() for this purpose, but that doesn't permit
     485             :  * use of a pager; moreover libedit's implementation behaves incompatibly
     486             :  * (preferring to encode its output) and may fail outright when the target
     487             :  * file is specified as /dev/tty.
     488             :  */
     489             : bool
     490           0 : printHistory(const char *fname, unsigned short int pager)
     491             : {
     492             : #ifdef USE_READLINE
     493             :     FILE       *output;
     494             :     bool        is_pager;
     495             : 
     496           0 :     if (!useHistory)
     497           0 :         return false;
     498             : 
     499           0 :     if (fname == NULL)
     500             :     {
     501             :         /* use pager, if enabled, when printing to console */
     502           0 :         output = PageOutput(INT_MAX, pager ? &(pset.popt.topt) : NULL);
     503           0 :         is_pager = true;
     504             :     }
     505             :     else
     506             :     {
     507           0 :         output = fopen(fname, "w");
     508           0 :         if (output == NULL)
     509             :         {
     510           0 :             psql_error("could not save history to file \"%s\": %s\n",
     511           0 :                        fname, strerror(errno));
     512           0 :             return false;
     513             :         }
     514           0 :         is_pager = false;
     515             :     }
     516             : 
     517           0 :     BEGIN_ITERATE_HISTORY(cur_hist);
     518             :     {
     519           0 :         fprintf(output, "%s\n", cur_hist->line);
     520             :     }
     521             :     END_ITERATE_HISTORY();
     522             : 
     523           0 :     if (is_pager)
     524           0 :         ClosePager(output);
     525             :     else
     526           0 :         fclose(output);
     527             : 
     528           0 :     return true;
     529             : #else
     530             :     psql_error("history is not supported by this installation\n");
     531             :     return false;
     532             : #endif
     533             : }
     534             : 
     535             : 
     536             : static void
     537           0 : finishInput(void)
     538             : {
     539             : #ifdef USE_READLINE
     540           0 :     if (useHistory && psql_history)
     541             :     {
     542           0 :         (void) saveHistory(psql_history, pset.histsize);
     543           0 :         free(psql_history);
     544           0 :         psql_history = NULL;
     545             :     }
     546             : #endif
     547           0 : }

Generated by: LCOV version 1.11