~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/bin/psql/input.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * psql - the PostgreSQL interactive terminal
 
3
 *
 
4
 * Copyright (c) 2000-2005, PostgreSQL Global Development Group
 
5
 *
 
6
 * $PostgreSQL: pgsql/src/bin/psql/input.c,v 1.43 2005-01-06 18:29:09 tgl Exp $
 
7
 */
 
8
#include "postgres_fe.h"
 
9
 
 
10
#include "input.h"
 
11
#include "pqexpbuffer.h"
 
12
#include "settings.h"
 
13
#include "tab-complete.h"
 
14
#include "common.h"
 
15
 
 
16
#ifndef WIN32
 
17
#define PSQLHISTORY ".psql_history"
 
18
#else
 
19
#define PSQLHISTORY "psql_history"
 
20
#endif
 
21
 
 
22
/* Runtime options for turning off readline and history */
 
23
/* (of course there is no runtime command for doing that :) */
 
24
#ifdef USE_READLINE
 
25
static bool useReadline;
 
26
static bool useHistory;
 
27
 
 
28
enum histcontrol
 
29
{
 
30
        hctl_none = 0,
 
31
        hctl_ignorespace = 1,
 
32
        hctl_ignoredups = 2,
 
33
        hctl_ignoreboth = hctl_ignorespace | hctl_ignoredups
 
34
};
 
35
#endif
 
36
 
 
37
#ifdef HAVE_ATEXIT
 
38
static void finishInput(void);
 
39
#else
 
40
/* designed for use with on_exit() */
 
41
static void finishInput(int, void *);
 
42
#endif
 
43
 
 
44
 
 
45
#ifdef USE_READLINE
 
46
static enum histcontrol
 
47
GetHistControlConfig(void)
 
48
{
 
49
        enum histcontrol HC;
 
50
        const char *var;
 
51
 
 
52
        var = GetVariable(pset.vars, "HISTCONTROL");
 
53
 
 
54
        if (!var)
 
55
                HC = hctl_none;
 
56
        else if (strcmp(var, "ignorespace") == 0)
 
57
                HC = hctl_ignorespace;
 
58
        else if (strcmp(var, "ignoredups") == 0)
 
59
                HC = hctl_ignoredups;
 
60
        else if (strcmp(var, "ignoreboth") == 0)
 
61
                HC = hctl_ignoreboth;
 
62
        else
 
63
                HC = hctl_none;
 
64
 
 
65
        return HC;
 
66
}
 
67
#endif
 
68
 
 
69
 
 
70
static char *
 
71
gets_basic(const char prompt[])
 
72
{
 
73
        fputs(prompt, stdout);
 
74
        fflush(stdout);
 
75
        return gets_fromFile(stdin);
 
76
}
 
77
 
 
78
 
 
79
/*
 
80
 * gets_interactive()
 
81
 *
 
82
 * Gets a line of interactive input, using readline of desired.
 
83
 * The result is malloc'ed.
 
84
 */
 
85
char *
 
86
gets_interactive(const char *prompt)
 
87
{
 
88
#ifdef USE_READLINE
 
89
        char       *s;
 
90
 
 
91
        static char *prev_hist = NULL;
 
92
 
 
93
        if (useReadline)
 
94
                /* On some platforms, readline is declared as readline(char *) */
 
95
                s = readline((char *) prompt);
 
96
        else
 
97
                s = gets_basic(prompt);
 
98
 
 
99
        if (useHistory && s && s[0])
 
100
        {
 
101
                enum histcontrol HC;
 
102
 
 
103
                HC = GetHistControlConfig();
 
104
 
 
105
                if (((HC & hctl_ignorespace) && s[0] == ' ') ||
 
106
                        ((HC & hctl_ignoredups) && prev_hist && strcmp(s, prev_hist) == 0))
 
107
                {
 
108
                        /* Ignore this line as far as history is concerned */
 
109
                }
 
110
                else
 
111
                {
 
112
                        free(prev_hist);
 
113
                        prev_hist = pg_strdup(s);
 
114
                        add_history(s);
 
115
                }
 
116
        }
 
117
 
 
118
        return s;
 
119
#else
 
120
        return gets_basic(prompt);
 
121
#endif
 
122
}
 
123
 
 
124
 
 
125
 
 
126
/*
 
127
 * gets_fromFile
 
128
 *
 
129
 * Gets a line of noninteractive input from a file (which could be stdin).
 
130
 */
 
131
char *
 
132
gets_fromFile(FILE *source)
 
133
{
 
134
        PQExpBufferData buffer;
 
135
        char            line[1024];
 
136
 
 
137
        initPQExpBuffer(&buffer);
 
138
 
 
139
        while (fgets(line, sizeof(line), source) != NULL)
 
140
        {
 
141
                appendPQExpBufferStr(&buffer, line);
 
142
                if (buffer.data[buffer.len - 1] == '\n')
 
143
                {
 
144
                        buffer.data[buffer.len - 1] = '\0';
 
145
                        return buffer.data;
 
146
                }
 
147
        }
 
148
 
 
149
        if (buffer.len > 0)
 
150
                return buffer.data;             /* EOF after reading some bufferload(s) */
 
151
 
 
152
        /* EOF, so return null */
 
153
        termPQExpBuffer(&buffer);
 
154
        return NULL;
 
155
}
 
156
 
 
157
 
 
158
 
 
159
/*
 
160
 * Put any startup stuff related to input in here. It's good to maintain
 
161
 * abstraction this way.
 
162
 *
 
163
 * The only "flag" right now is 1 for use readline & history.
 
164
 */
 
165
void
 
166
initializeInput(int flags)
 
167
{
 
168
#ifdef USE_READLINE
 
169
        if (flags & 1)
 
170
        {
 
171
                char            home[MAXPGPATH];
 
172
 
 
173
                useReadline = true;
 
174
                initialize_readline();
 
175
 
 
176
                useHistory = true;
 
177
                if (GetVariable(pset.vars, "HISTSIZE") == NULL)
 
178
                        SetVariable(pset.vars, "HISTSIZE", "500");
 
179
                using_history();
 
180
                if (get_home_path(home))
 
181
                {
 
182
                        char       *psql_history;
 
183
 
 
184
                        psql_history = pg_malloc(strlen(home) + 1 +
 
185
                                                                         strlen(PSQLHISTORY) + 1);
 
186
                        sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
 
187
                        read_history(psql_history);
 
188
                        free(psql_history);
 
189
                }
 
190
        }
 
191
#endif
 
192
 
 
193
#ifdef HAVE_ATEXIT
 
194
        atexit(finishInput);
 
195
#else
 
196
        on_exit(finishInput, NULL);
 
197
#endif
 
198
}
 
199
 
 
200
 
 
201
 
 
202
bool
 
203
saveHistory(char *fname)
 
204
{
 
205
#ifdef USE_READLINE
 
206
        if (useHistory && fname)
 
207
        {
 
208
                if (write_history(fname) == 0)
 
209
                        return true;
 
210
 
 
211
                psql_error("could not save history to file \"%s\": %s\n", fname, strerror(errno));
 
212
        }
 
213
#else
 
214
                psql_error("history is not supported by this installation\n");
 
215
#endif
 
216
 
 
217
        return false;
 
218
}
 
219
 
 
220
 
 
221
 
 
222
static void
 
223
#ifdef HAVE_ATEXIT
 
224
finishInput(void)
 
225
#else
 
226
finishInput(int exitstatus, void *arg)
 
227
#endif
 
228
{
 
229
#ifdef USE_READLINE
 
230
        if (useHistory)
 
231
        {
 
232
                char            home[MAXPGPATH];
 
233
 
 
234
                if (get_home_path(home))
 
235
                {
 
236
                        char       *psql_history;
 
237
                        int                     hist_size;
 
238
 
 
239
                        hist_size = GetVariableNum(pset.vars, "HISTSIZE", -1, -1, true);
 
240
                        if (hist_size >= 0)
 
241
                                stifle_history(hist_size);
 
242
 
 
243
                        psql_history = pg_malloc(strlen(home) + 1 +
 
244
                                                                         strlen(PSQLHISTORY) + 1);
 
245
                        sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
 
246
                        write_history(psql_history);
 
247
                        free(psql_history);
 
248
                }
 
249
        }
 
250
#endif
 
251
}