PostgreSQL Source Code  git master
input.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include "common.h"
#include "common/logging.h"
#include "input.h"
#include "settings.h"
#include "tab-complete.h"
Include dependency graph for input.c:

Go to the source code of this file.

Macros

#define PSQLHISTORY   ".psql_history"
 

Functions

static void finishInput (void)
 
char * gets_interactive (const char *prompt, PQExpBuffer query_buf)
 
void pg_append_history (const char *s, PQExpBuffer history_buf)
 
void pg_send_history (PQExpBuffer history_buf)
 
char * gets_fromFile (FILE *source)
 
void initializeInput (int flags)
 
bool printHistory (const char *fname, unsigned short int pager)
 

Macro Definition Documentation

◆ PSQLHISTORY

#define PSQLHISTORY   ".psql_history"

Definition at line 23 of file input.c.

Referenced by initializeInput().

Function Documentation

◆ finishInput()

static void finishInput ( void  )
static

Definition at line 535 of file input.c.

References free, _psqlSettings::histsize, and pset.

Referenced by initializeInput().

536 {
537 #ifdef USE_READLINE
538  if (useHistory && psql_history)
539  {
540  (void) saveHistory(psql_history, pset.histsize);
541  free(psql_history);
542  psql_history = NULL;
543  }
544 #endif
545 }
PsqlSettings pset
Definition: startup.c:31
#define free(a)
Definition: header.h:65

◆ gets_fromFile()

char* gets_fromFile ( FILE *  source)

Definition at line 188 of file input.c.

References appendPQExpBufferStr(), createPQExpBuffer(), PQExpBufferData::data, PQExpBufferData::len, pg_log_error, pg_strdup(), PQExpBufferBroken, resetPQExpBuffer(), and sigint_interrupt_enabled.

Referenced by exec_command_prompt(), gets_interactive(), and MainLoop().

189 {
190  static PQExpBuffer buffer = NULL;
191 
192  char line[1024];
193 
194  if (buffer == NULL) /* first time through? */
195  buffer = createPQExpBuffer();
196  else
197  resetPQExpBuffer(buffer);
198 
199  for (;;)
200  {
201  char *result;
202 
203  /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
205 
206  /* Get some data */
207  result = fgets(line, sizeof(line), source);
208 
209  /* Disable SIGINT again */
210  sigint_interrupt_enabled = false;
211 
212  /* EOF or error? */
213  if (result == NULL)
214  {
215  if (ferror(source))
216  {
217  pg_log_error("could not read from input file: %m");
218  return NULL;
219  }
220  break;
221  }
222 
223  appendPQExpBufferStr(buffer, line);
224 
225  if (PQExpBufferBroken(buffer))
226  {
227  pg_log_error("out of memory");
228  return NULL;
229  }
230 
231  /* EOL? */
232  if (buffer->len > 0 && buffer->data[buffer->len - 1] == '\n')
233  {
234  buffer->data[buffer->len - 1] = '\0';
235  return pg_strdup(buffer->data);
236  }
237  }
238 
239  if (buffer->len > 0) /* EOF after reading some bufferload(s) */
240  return pg_strdup(buffer->data);
241 
242  /* EOF, so return null */
243  return NULL;
244 }
volatile bool sigint_interrupt_enabled
Definition: common.c:245
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:74
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148

◆ gets_interactive()

char* gets_interactive ( const char *  prompt,
PQExpBuffer  query_buf 
)

Definition at line 67 of file input.c.

References gets_fromFile(), sigint_interrupt_enabled, generate_unaccent_rules::stdout, and tab_completion_query_buf.

Referenced by MainLoop().

68 {
69 #ifdef USE_READLINE
70  if (useReadline)
71  {
72  char *result;
73 
74  /*
75  * Some versions of readline don't notice SIGWINCH signals that arrive
76  * when not actively reading input. The simplest fix is to always
77  * re-read the terminal size. This leaves a window for SIGWINCH to be
78  * missed between here and where readline() enables libreadline's
79  * signal handler, but that's probably short enough to be ignored.
80  */
81 #ifdef HAVE_RL_RESET_SCREEN_SIZE
82  rl_reset_screen_size();
83 #endif
84 
85  /* Make current query_buf available to tab completion callback */
86  tab_completion_query_buf = query_buf;
87 
88  /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
90 
91  /* On some platforms, readline is declared as readline(char *) */
92  result = readline((char *) prompt);
93 
94  /* Disable SIGINT again */
96 
97  /* Pure neatnik-ism */
99 
100  return result;
101  }
102 #endif
103 
104  fputs(prompt, stdout);
105  fflush(stdout);
106  return gets_fromFile(stdin);
107 }
volatile bool sigint_interrupt_enabled
Definition: common.c:245
char * gets_fromFile(FILE *source)
Definition: input.c:188
PQExpBuffer tab_completion_query_buf

◆ initializeInput()

void initializeInput ( int  flags)

Definition at line 346 of file input.c.

References close, DEVNULL, expand_tilde(), fd(), finishInput(), get_home_path(), GetVariable(), initialize_readline(), Max, MAXPGPATH, Min, PG_BINARY, pg_log_error, pg_strdup(), pset, psprintf(), PSQLHISTORY, and _psqlSettings::vars.

Referenced by main().

347 {
348 #ifdef USE_READLINE
349  if (flags & 1)
350  {
351  const char *histfile;
352  char home[MAXPGPATH];
353 
354  useReadline = true;
355 
356  /* these two things must be done in this order: */
358  rl_initialize();
359 
360  useHistory = true;
361  using_history();
362  history_lines_added = 0;
363 
364  histfile = GetVariable(pset.vars, "HISTFILE");
365 
366  if (histfile == NULL)
367  {
368  char *envhist;
369 
370  envhist = getenv("PSQL_HISTORY");
371  if (envhist != NULL && strlen(envhist) > 0)
372  histfile = envhist;
373  }
374 
375  if (histfile == NULL)
376  {
377  if (get_home_path(home))
378  psql_history = psprintf("%s/%s", home, PSQLHISTORY);
379  }
380  else
381  {
382  psql_history = pg_strdup(histfile);
383  expand_tilde(&psql_history);
384  }
385 
386  if (psql_history)
387  {
388  read_history(psql_history);
389  decode_history();
390  }
391  }
392 #endif
393 
394  atexit(finishInput);
395 }
static void finishInput(void)
Definition: input.c:535
PsqlSettings pset
Definition: startup.c:31
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define PSQLHISTORY
Definition: input.c:23
void expand_tilde(char **filename)
Definition: common.c:2220
#define MAXPGPATH
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:71
void initialize_readline(void)
bool get_home_path(char *ret_path)
Definition: path.c:807
VariableSpace vars
Definition: settings.h:117

◆ pg_append_history()

void pg_append_history ( const char *  s,
PQExpBuffer  history_buf 
)

Definition at line 114 of file input.c.

References appendPQExpBufferChar(), and appendPQExpBufferStr().

Referenced by MainLoop().

115 {
116 #ifdef USE_READLINE
117  if (useHistory && s)
118  {
119  appendPQExpBufferStr(history_buf, s);
120  if (!s[0] || s[strlen(s) - 1] != '\n')
121  appendPQExpBufferChar(history_buf, '\n');
122  }
123 #endif
124 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380

◆ pg_send_history()

void pg_send_history ( PQExpBuffer  history_buf)

Definition at line 136 of file input.c.

References PQExpBufferData::data, free, hctl_ignoredups, hctl_ignorespace, _psqlSettings::histcontrol, i, pg_strdup(), pset, and resetPQExpBuffer().

Referenced by MainLoop().

137 {
138 #ifdef USE_READLINE
139  static char *prev_hist = NULL;
140 
141  char *s = history_buf->data;
142  int i;
143 
144  /* Trim any trailing \n's (OK to scribble on history_buf) */
145  for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
146  ;
147  s[i + 1] = '\0';
148 
149  if (useHistory && s[0])
150  {
151  if (((pset.histcontrol & hctl_ignorespace) &&
152  s[0] == ' ') ||
154  prev_hist && strcmp(s, prev_hist) == 0))
155  {
156  /* Ignore this line as far as history is concerned */
157  }
158  else
159  {
160  /* Save each previous line for ignoredups processing */
161  if (prev_hist)
162  free(prev_hist);
163  prev_hist = pg_strdup(s);
164  /* And send it to readline */
165  add_history(s);
166  /* Count lines added to history for use later */
167  history_lines_added++;
168  }
169  }
170 
171  resetPQExpBuffer(history_buf);
172 #endif
173 }
PsqlSettings pset
Definition: startup.c:31
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define free(a)
Definition: header.h:65
int i
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
HistControl histcontrol
Definition: settings.h:137

◆ printHistory()

bool printHistory ( const char *  fname,
unsigned short int  pager 
)

Definition at line 489 of file input.c.

References ClosePager(), fprintf, output(), PageOutput(), pg_log_error, _psqlSettings::popt, pset, and printQueryOpt::topt.

Referenced by exec_command_s().

490 {
491 #ifdef USE_READLINE
492  FILE *output;
493  bool is_pager;
494 
495  if (!useHistory)
496  return false;
497 
498  if (fname == NULL)
499  {
500  /* use pager, if enabled, when printing to console */
501  output = PageOutput(INT_MAX, pager ? &(pset.popt.topt) : NULL);
502  is_pager = true;
503  }
504  else
505  {
506  output = fopen(fname, "w");
507  if (output == NULL)
508  {
509  pg_log_error("could not save history to file \"%s\": %m", fname);
510  return false;
511  }
512  is_pager = false;
513  }
514 
515  BEGIN_ITERATE_HISTORY(cur_hist);
516  {
517  fprintf(output, "%s\n", cur_hist->line);
518  }
519  END_ITERATE_HISTORY();
520 
521  if (is_pager)
522  ClosePager(output);
523  else
524  fclose(output);
525 
526  return true;
527 #else
528  pg_log_error("history is not supported by this installation");
529  return false;
530 #endif
531 }
PsqlSettings pset
Definition: startup.c:31
static void output(uint64 loop_count)
#define pg_log_error(...)
Definition: logging.h:79
void ClosePager(FILE *pagerpipe)
Definition: print.c:3043
printTableOpt topt
Definition: print.h:167
#define fprintf
Definition: port.h:196
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:2992
printQueryOpt popt
Definition: settings.h:91