Go to the documentation of this file.00001
00002
00003
00004
00005
00006
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
00027
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
00039
00040
00041
00042
00043
00044
00045 #define NL_IN_HISTORY 0x01
00046 #endif
00047
00048 static void finishInput(void);
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 char *
00060 gets_interactive(const char *prompt)
00061 {
00062 #ifdef USE_READLINE
00063 if (useReadline)
00064 {
00065 char *result;
00066
00067
00068 sigint_interrupt_enabled = true;
00069
00070
00071 result = readline((char *) prompt);
00072
00073
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
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
00105
00106
00107
00108
00109
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
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
00133 }
00134 else
00135 {
00136
00137 if (prev_hist)
00138 free(prev_hist);
00139 prev_hist = pg_strdup(s);
00140
00141 add_history(s);
00142
00143 history_lines_added++;
00144 }
00145 }
00146
00147 resetPQExpBuffer(history_buf);
00148 #endif
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 char *
00164 gets_fromFile(FILE *source)
00165 {
00166 static PQExpBuffer buffer = NULL;
00167
00168 char line[1024];
00169
00170 if (buffer == NULL)
00171 buffer = createPQExpBuffer();
00172 else
00173 resetPQExpBuffer(buffer);
00174
00175 for (;;)
00176 {
00177 char *result;
00178
00179
00180 sigint_interrupt_enabled = true;
00181
00182
00183 result = fgets(line, sizeof(line), source);
00184
00185
00186 sigint_interrupt_enabled = false;
00187
00188
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
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)
00217 return pg_strdup(buffer->data);
00218
00219
00220 return NULL;
00221 }
00222
00223
00224 #ifdef USE_READLINE
00225
00226
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
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
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
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
00263
00264
00265
00266
00267
00268
00269
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
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 bool
00341 saveHistory(char *fname, int max_lines, bool appendFlag, bool encodeFlag)
00342 {
00343 #ifdef USE_READLINE
00344
00345
00346
00347
00348
00349
00350
00351 if (useHistory && fname &&
00352 strcmp(fname, DEVNULL) != 0)
00353 {
00354 if (encodeFlag)
00355 encode_history();
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 #if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
00369 if (appendFlag)
00370 {
00371 int nlines;
00372 int fd;
00373
00374
00375 if (max_lines >= 0)
00376 {
00377 nlines = Max(max_lines - history_lines_added, 0);
00378 (void) history_truncate_file(fname, nlines);
00379 }
00380
00381 fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
00382 if (fd >= 0)
00383 close(fd);
00384
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
00398 if (max_lines >= 0)
00399 stifle_history(max_lines);
00400
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
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 }