Header And Logo

PostgreSQL
| The world's most advanced open source database.

input.c

Go to the documentation of this file.
00001 /*
00002  * psql - the PostgreSQL interactive terminal
00003  *
00004  * Copyright (c) 2000-2013, PostgreSQL Global Development Group
00005  *
00006  * src/bin/psql/input.c
00007  */
00008 #include "postgres_fe.h"
00009 
00010 #ifndef WIN32
00011 #include <unistd.h>
00012 #endif
00013 #include <fcntl.h>
00014 
00015 #include "input.h"
00016 #include "settings.h"
00017 #include "tab-complete.h"
00018 #include "common.h"
00019 
00020 #ifndef WIN32
00021 #define PSQLHISTORY ".psql_history"
00022 #else
00023 #define PSQLHISTORY "psql_history"
00024 #endif
00025 
00026 /* Runtime options for turning off readline and history */
00027 /* (of course there is no runtime command for doing that :) */
00028 #ifdef USE_READLINE
00029 static bool useReadline;
00030 static bool useHistory;
00031 
00032 static char *psql_history;
00033 
00034 static int  history_lines_added;
00035 
00036 
00037 /*
00038  *  Preserve newlines in saved queries by mapping '\n' to NL_IN_HISTORY
00039  *
00040  *  It is assumed NL_IN_HISTORY will never be entered by the user
00041  *  nor appear inside a multi-byte string.  0x00 is not properly
00042  *  handled by the readline routines so it can not be used
00043  *  for this purpose.
00044  */
00045 #define NL_IN_HISTORY   0x01
00046 #endif
00047 
00048 static void finishInput(void);
00049 
00050 
00051 /*
00052  * gets_interactive()
00053  *
00054  * Gets a line of interactive input, using readline if desired.
00055  * The result is a malloc'd string.
00056  *
00057  * Caller *must* have set up sigint_interrupt_jmp before calling.
00058  */
00059 char *
00060 gets_interactive(const char *prompt)
00061 {
00062 #ifdef USE_READLINE
00063     if (useReadline)
00064     {
00065         char       *result;
00066 
00067         /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
00068         sigint_interrupt_enabled = true;
00069 
00070         /* On some platforms, readline is declared as readline(char *) */
00071         result = readline((char *) prompt);
00072 
00073         /* Disable SIGINT again */
00074         sigint_interrupt_enabled = false;
00075 
00076         return result;
00077     }
00078 #endif
00079 
00080     fputs(prompt, stdout);
00081     fflush(stdout);
00082     return gets_fromFile(stdin);
00083 }
00084 
00085 
00086 /*
00087  * Append the line to the history buffer, making sure there is a trailing '\n'
00088  */
00089 void
00090 pg_append_history(const char *s, PQExpBuffer history_buf)
00091 {
00092 #ifdef USE_READLINE
00093     if (useHistory && s)
00094     {
00095         appendPQExpBufferStr(history_buf, s);
00096         if (!s[0] || s[strlen(s) - 1] != '\n')
00097             appendPQExpBufferChar(history_buf, '\n');
00098     }
00099 #endif
00100 }
00101 
00102 
00103 /*
00104  * Emit accumulated history entry to readline's history mechanism,
00105  * then reset the buffer to empty.
00106  *
00107  * Note: we write nothing if history_buf is empty, so extra calls to this
00108  * function don't hurt.  There must have been at least one line added by
00109  * pg_append_history before we'll do anything.
00110  */
00111 void
00112 pg_send_history(PQExpBuffer history_buf)
00113 {
00114 #ifdef USE_READLINE
00115     static char *prev_hist = NULL;
00116 
00117     char       *s = history_buf->data;
00118     int         i;
00119 
00120     /* Trim any trailing \n's (OK to scribble on history_buf) */
00121     for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
00122         ;
00123     s[i + 1] = '\0';
00124 
00125     if (useHistory && s[0])
00126     {
00127         if (((pset.histcontrol & hctl_ignorespace) &&
00128              s[0] == ' ') ||
00129             ((pset.histcontrol & hctl_ignoredups) &&
00130              prev_hist && strcmp(s, prev_hist) == 0))
00131         {
00132             /* Ignore this line as far as history is concerned */
00133         }
00134         else
00135         {
00136             /* Save each previous line for ignoredups processing */
00137             if (prev_hist)
00138                 free(prev_hist);
00139             prev_hist = pg_strdup(s);
00140             /* And send it to readline */
00141             add_history(s);
00142             /* Count lines added to history for use later */
00143             history_lines_added++;
00144         }
00145     }
00146 
00147     resetPQExpBuffer(history_buf);
00148 #endif
00149 }
00150 
00151 
00152 /*
00153  * gets_fromFile
00154  *
00155  * Gets a line of noninteractive input from a file (which could be stdin).
00156  * The result is a malloc'd string, or NULL on EOF or input error.
00157  *
00158  * Caller *must* have set up sigint_interrupt_jmp before calling.
00159  *
00160  * Note: we re-use a static PQExpBuffer for each call.  This is to avoid
00161  * leaking memory if interrupted by SIGINT.
00162  */
00163 char *
00164 gets_fromFile(FILE *source)
00165 {
00166     static PQExpBuffer buffer = NULL;
00167 
00168     char        line[1024];
00169 
00170     if (buffer == NULL)         /* first time through? */
00171         buffer = createPQExpBuffer();
00172     else
00173         resetPQExpBuffer(buffer);
00174 
00175     for (;;)
00176     {
00177         char       *result;
00178 
00179         /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
00180         sigint_interrupt_enabled = true;
00181 
00182         /* Get some data */
00183         result = fgets(line, sizeof(line), source);
00184 
00185         /* Disable SIGINT again */
00186         sigint_interrupt_enabled = false;
00187 
00188         /* EOF or error? */
00189         if (result == NULL)
00190         {
00191             if (ferror(source))
00192             {
00193                 psql_error("could not read from input file: %s\n",
00194                            strerror(errno));
00195                 return NULL;
00196             }
00197             break;
00198         }
00199 
00200         appendPQExpBufferStr(buffer, line);
00201 
00202         if (PQExpBufferBroken(buffer))
00203         {
00204             psql_error("out of memory\n");
00205             return NULL;
00206         }
00207 
00208         /* EOL? */
00209         if (buffer->data[buffer->len - 1] == '\n')
00210         {
00211             buffer->data[buffer->len - 1] = '\0';
00212             return pg_strdup(buffer->data);
00213         }
00214     }
00215 
00216     if (buffer->len > 0)        /* EOF after reading some bufferload(s) */
00217         return pg_strdup(buffer->data);
00218 
00219     /* EOF, so return null */
00220     return NULL;
00221 }
00222 
00223 
00224 #ifdef USE_READLINE
00225 /*
00226  * Convert newlines to NL_IN_HISTORY for safe saving in readline history file
00227  */
00228 static void
00229 encode_history(void)
00230 {
00231     HIST_ENTRY *cur_hist;
00232     char       *cur_ptr;
00233 
00234     history_set_pos(0);
00235     for (cur_hist = current_history(); cur_hist; cur_hist = next_history())
00236     {
00237         /* some platforms declare HIST_ENTRY.line as const char * */
00238         for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
00239             if (*cur_ptr == '\n')
00240                 *cur_ptr = NL_IN_HISTORY;
00241     }
00242 }
00243 
00244 /*
00245  * Reverse the above encoding
00246  */
00247 static void
00248 decode_history(void)
00249 {
00250     HIST_ENTRY *cur_hist;
00251     char       *cur_ptr;
00252 
00253     history_set_pos(0);
00254     for (cur_hist = current_history(); cur_hist; cur_hist = next_history())
00255     {
00256         /* some platforms declare HIST_ENTRY.line as const char * */
00257         for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
00258             if (*cur_ptr == NL_IN_HISTORY)
00259                 *cur_ptr = '\n';
00260     }
00261 }
00262 #endif   /* USE_READLINE */
00263 
00264 
00265 /*
00266  * Put any startup stuff related to input in here. It's good to maintain
00267  * abstraction this way.
00268  *
00269  * The only "flag" right now is 1 for use readline & history.
00270  */
00271 void
00272 initializeInput(int flags)
00273 {
00274 #ifdef USE_READLINE
00275     if (flags & 1)
00276     {
00277         const char *histfile;
00278         char        home[MAXPGPATH];
00279 
00280         useReadline = true;
00281         initialize_readline();
00282 
00283         useHistory = true;
00284         using_history();
00285         history_lines_added = 0;
00286 
00287         histfile = GetVariable(pset.vars, "HISTFILE");
00288 
00289         if (histfile == NULL)
00290         {
00291             char       *envhist;
00292 
00293             envhist = getenv("PSQL_HISTORY");
00294             if (envhist != NULL && strlen(envhist) > 0)
00295                 histfile = envhist;
00296         }
00297 
00298         if (histfile == NULL)
00299         {
00300             if (get_home_path(home))
00301             {
00302                 psql_history = pg_malloc(strlen(home) + 1 +
00303                                          strlen(PSQLHISTORY) + 1);
00304                 snprintf(psql_history, MAXPGPATH, "%s/%s", home, PSQLHISTORY);
00305             }
00306         }
00307         else
00308         {
00309             psql_history = pg_strdup(histfile);
00310             expand_tilde(&psql_history);
00311         }
00312 
00313         if (psql_history)
00314         {
00315             read_history(psql_history);
00316             decode_history();
00317         }
00318     }
00319 #endif
00320 
00321     atexit(finishInput);
00322 }
00323 
00324 
00325 /*
00326  * This function saves the readline history when user
00327  * runs \s command or when psql exits.
00328  *
00329  * fname: pathname of history file.  (Should really be "const char *",
00330  * but some ancient versions of readline omit the const-decoration.)
00331  *
00332  * max_lines: if >= 0, limit history file to that many entries.
00333  *
00334  * appendFlag: if true, try to append just our new lines to the file.
00335  * If false, write the whole available history.
00336  *
00337  * encodeFlag: whether to encode \n as \x01.  For \s calls we don't wish
00338  * to do that, but must do so when saving the final history file.
00339  */
00340 bool
00341 saveHistory(char *fname, int max_lines, bool appendFlag, bool encodeFlag)
00342 {
00343 #ifdef USE_READLINE
00344 
00345     /*
00346      * Suppressing the write attempt when HISTFILE is set to /dev/null may
00347      * look like a negligible optimization, but it's necessary on e.g. Darwin,
00348      * where write_history will fail because it tries to chmod the target
00349      * file.
00350      */
00351     if (useHistory && fname &&
00352         strcmp(fname, DEVNULL) != 0)
00353     {
00354         if (encodeFlag)
00355             encode_history();
00356 
00357         /*
00358          * On newer versions of libreadline, truncate the history file as
00359          * needed and then append what we've added.  This avoids overwriting
00360          * history from other concurrent sessions (although there are still
00361          * race conditions when two sessions exit at about the same time). If
00362          * we don't have those functions, fall back to write_history().
00363          *
00364          * Note: return value of write_history is not standardized across GNU
00365          * readline and libedit.  Therefore, check for errno becoming set to
00366          * see if the write failed.  Similarly for append_history.
00367          */
00368 #if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
00369         if (appendFlag)
00370         {
00371             int         nlines;
00372             int         fd;
00373 
00374             /* truncate previous entries if needed */
00375             if (max_lines >= 0)
00376             {
00377                 nlines = Max(max_lines - history_lines_added, 0);
00378                 (void) history_truncate_file(fname, nlines);
00379             }
00380             /* append_history fails if file doesn't already exist :-( */
00381             fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
00382             if (fd >= 0)
00383                 close(fd);
00384             /* append the appropriate number of lines */
00385             if (max_lines >= 0)
00386                 nlines = Min(max_lines, history_lines_added);
00387             else
00388                 nlines = history_lines_added;
00389             errno = 0;
00390             (void) append_history(nlines, fname);
00391             if (errno == 0)
00392                 return true;
00393         }
00394         else
00395 #endif
00396         {
00397             /* truncate what we have ... */
00398             if (max_lines >= 0)
00399                 stifle_history(max_lines);
00400             /* ... and overwrite file.  Tough luck for concurrent sessions. */
00401             errno = 0;
00402             (void) write_history(fname);
00403             if (errno == 0)
00404                 return true;
00405         }
00406 
00407         psql_error("could not save history to file \"%s\": %s\n",
00408                    fname, strerror(errno));
00409     }
00410 #else
00411     /* only get here in \s case, so complain */
00412     psql_error("history is not supported by this installation\n");
00413 #endif
00414 
00415     return false;
00416 }
00417 
00418 
00419 static void
00420 finishInput(void)
00421 {
00422 #ifdef USE_READLINE
00423     if (useHistory && psql_history)
00424     {
00425         int         hist_size;
00426 
00427         hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true);
00428         saveHistory(psql_history, hist_size, true, true);
00429         free(psql_history);
00430         psql_history = NULL;
00431     }
00432 #endif
00433 }