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.

Function Documentation

◆ finishInput()

static void finishInput ( void  )
static

Definition at line 540 of file input.c.

541 {
542 #ifdef USE_READLINE
543  if (useHistory && psql_history)
544  {
545  (void) saveHistory(psql_history, pset.histsize);
546  free(psql_history);
547  psql_history = NULL;
548  }
549 #endif
550 }
#define free(a)
Definition: header.h:65
PsqlSettings pset
Definition: startup.c:32

References free, _psqlSettings::histsize, and pset.

Referenced by initializeInput().

◆ gets_fromFile()

char* gets_fromFile ( FILE *  source)

Definition at line 186 of file input.c.

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

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

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

◆ gets_interactive()

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

Definition at line 67 of file input.c.

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  result = readline(prompt);
92 
93  /* Disable SIGINT again */
95 
96  /* Pure neatnik-ism */
98 
99  return result;
100  }
101 #endif
102 
103  fputs(prompt, stdout);
104  fflush(stdout);
105  return gets_fromFile(stdin);
106 }
char * gets_fromFile(FILE *source)
Definition: input.c:186
static void const char fflush(stdout)
PQExpBuffer tab_completion_query_buf

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

Referenced by MainLoop().

◆ initializeInput()

void initializeInput ( int  flags)

Definition at line 344 of file input.c.

345 {
346 #ifdef USE_READLINE
347  if (flags & 1)
348  {
349  const char *histfile;
350  char home[MAXPGPATH];
351 
352  useReadline = true;
353 
354  /* set appropriate values for Readline's global variables */
356 
357 #ifdef HAVE_RL_VARIABLE_BIND
358  /* set comment-begin to a useful value for SQL */
359  (void) rl_variable_bind("comment-begin", "-- ");
360 #endif
361 
362  /* this reads ~/.inputrc, so do it after rl_variable_bind */
363  rl_initialize();
364 
365  useHistory = true;
366  using_history();
367  history_lines_added = 0;
368 
369  histfile = GetVariable(pset.vars, "HISTFILE");
370 
371  if (histfile == NULL)
372  {
373  char *envhist;
374 
375  envhist = getenv("PSQL_HISTORY");
376  if (envhist != NULL && strlen(envhist) > 0)
377  histfile = envhist;
378  }
379 
380  if (histfile == NULL)
381  {
382  if (get_home_path(home))
383  psql_history = psprintf("%s/%s", home, PSQLHISTORY);
384  }
385  else
386  {
387  psql_history = pg_strdup(histfile);
388  expand_tilde(&psql_history);
389  }
390 
391  if (psql_history)
392  {
393  read_history(psql_history);
394  decode_history();
395  }
396  }
397 #endif
398 
399  atexit(finishInput);
400 }
void expand_tilde(char **filename)
Definition: common.c:2195
static void finishInput(void)
Definition: input.c:540
#define PSQLHISTORY
Definition: input.c:23
#define MAXPGPATH
bool get_home_path(char *ret_path)
Definition: path.c:928
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
VariableSpace vars
Definition: settings.h:133
void initialize_readline(void)
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:71

References expand_tilde(), finishInput(), get_home_path(), GetVariable(), initialize_readline(), MAXPGPATH, pg_strdup(), pset, psprintf(), PSQLHISTORY, and _psqlSettings::vars.

Referenced by main().

◆ pg_append_history()

void pg_append_history ( const char *  s,
PQExpBuffer  history_buf 
)

Definition at line 113 of file input.c.

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

References appendPQExpBufferChar(), and appendPQExpBufferStr().

Referenced by MainLoop().

◆ pg_send_history()

void pg_send_history ( PQExpBuffer  history_buf)

Definition at line 135 of file input.c.

136 {
137 #ifdef USE_READLINE
138  static char *prev_hist = NULL;
139 
140  char *s = history_buf->data;
141  int i;
142 
143  /* Trim any trailing \n's (OK to scribble on history_buf) */
144  for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
145  ;
146  s[i + 1] = '\0';
147 
148  if (useHistory && s[0])
149  {
150  if (((pset.histcontrol & hctl_ignorespace) &&
151  s[0] == ' ') ||
153  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  free(prev_hist);
161  prev_hist = pg_strdup(s);
162  /* And send it to readline */
163  add_history(s);
164  /* Count lines added to history for use later */
165  history_lines_added++;
166  }
167  }
168 
169  resetPQExpBuffer(history_buf);
170 #endif
171 }
int i
Definition: isn.c:72
@ hctl_ignoredups
Definition: settings.h:78
@ hctl_ignorespace
Definition: settings.h:77
HistControl histcontrol
Definition: settings.h:161

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

Referenced by MainLoop().

◆ printHistory()

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

Definition at line 494 of file input.c.

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

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

Referenced by exec_command_s().