PostgreSQL Source Code git master
Macros | Functions
prompt.c File Reference
#include "postgres_fe.h"
#include "common.h"
#include "common/string.h"
#include "input.h"
#include "libpq/pqcomm.h"
#include "prompt.h"
#include "settings.h"
Include dependency graph for prompt.c:

Go to the source code of this file.

Macros

#define  MAX_PROMPT_SIZE   256
 

Functions

char *  get_prompt (promptStatus_t status, ConditionalStack cstack)
 

Macro Definition Documentation

MAX_PROMPT_SIZE

#define MAX_PROMPT_SIZE   256

Function Documentation

get_prompt()

char * get_prompt ( promptStatus_t  status,
ConditionalStack  cstack 
)

Definition at line 68 of file prompt.c.

69{
70#define MAX_PROMPT_SIZE 256
71 static char destination[MAX_PROMPT_SIZE + 1];
72 char buf[MAX_PROMPT_SIZE + 1];
73 bool esc = false;
74 const char *p;
75 const char *prompt_string = "? ";
76 static size_t last_prompt1_width = 0;
77
78 switch (status)
79 {
80 case PROMPT_READY:
81 prompt_string = pset.prompt1;
82 break;
83
84 case PROMPT_CONTINUE:
88 case PROMPT_COMMENT:
89 case PROMPT_PAREN:
90 prompt_string = pset.prompt2;
91 break;
92
93 case PROMPT_COPY:
94 prompt_string = pset.prompt3;
95 break;
96 }
97
98 destination[0] = '0円';
99
100 for (p = prompt_string;
101 *p && strlen(destination) < sizeof(destination) - 1;
102 p++)
103 {
104 memset(buf, 0, sizeof(buf));
105 if (esc)
106 {
107 switch (*p)
108 {
109 /* Current database */
110 case '/':
111 if (pset.db)
112 strlcpy(buf, PQdb(pset.db), sizeof(buf));
113 break;
114 case '~':
115 if (pset.db)
116 {
117 const char *var;
118
119 if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
120 ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
121 strlcpy(buf, "~", sizeof(buf));
122 else
123 strlcpy(buf, PQdb(pset.db), sizeof(buf));
124 }
125 break;
126
127 /* Whitespace of the same width as the last PROMPT1 */
128 case 'w':
129 if (pset.db)
130 memset(buf, ' ',
131 Min(last_prompt1_width, sizeof(buf) - 1));
132 break;
133
134 /* DB server hostname (long/short) */
135 case 'M':
136 case 'm':
137 if (pset.db)
138 {
139 const char *host = PQhost(pset.db);
140
141 /* INET socket */
142 if (host && host[0] && !is_unixsock_path(host))
143 {
144 strlcpy(buf, host, sizeof(buf));
145 if (*p == 'm')
146 buf[strcspn(buf, ".")] = '0円';
147 }
148 /* UNIX socket */
149 else
150 {
151 if (!host
152 || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0
153 || *p == 'm')
154 strlcpy(buf, "[local]", sizeof(buf));
155 else
156 snprintf(buf, sizeof(buf), "[local:%s]", host);
157 }
158 }
159 break;
160 /* DB server port number */
161 case '>':
162 if (pset.db && PQport(pset.db))
163 strlcpy(buf, PQport(pset.db), sizeof(buf));
164 break;
165 /* DB server user name */
166 case 'n':
167 if (pset.db)
168 strlcpy(buf, session_username(), sizeof(buf));
169 break;
170 /* service name */
171 case 's':
172 {
173 const char *service_name = GetVariable(pset.vars, "SERVICE");
174
175 if (service_name)
176 strlcpy(buf, service_name, sizeof(buf));
177 }
178 break;
179 /* backend pid */
180 case 'p':
181 if (pset.db)
182 {
183 int pid = PQbackendPID(pset.db);
184
185 if (pid)
186 snprintf(buf, sizeof(buf), "%d", pid);
187 }
188 break;
189 /* pipeline status */
190 case 'P':
191 {
193
194 if (status == PQ_PIPELINE_ON)
195 strlcpy(buf, "on", sizeof(buf));
196 else if (status == PQ_PIPELINE_ABORTED)
197 strlcpy(buf, "abort", sizeof(buf));
198 else
199 strlcpy(buf, "off", sizeof(buf));
200 break;
201 }
202
203 case '0':
204 case '1':
205 case '2':
206 case '3':
207 case '4':
208 case '5':
209 case '6':
210 case '7':
211 *buf = (char) strtol(p, unconstify(char **, &p), 8);
212 --p;
213 break;
214 case 'R':
215 switch (status)
216 {
217 case PROMPT_READY:
218 if (cstack != NULL && !conditional_active(cstack))
219 buf[0] = '@';
220 else if (!pset.db)
221 buf[0] = '!';
222 else if (!pset.singleline)
223 buf[0] = '=';
224 else
225 buf[0] = '^';
226 break;
227 case PROMPT_CONTINUE:
228 buf[0] = '-';
229 break;
231 buf[0] = '\'';
232 break;
234 buf[0] = '"';
235 break;
237 buf[0] = '$';
238 break;
239 case PROMPT_COMMENT:
240 buf[0] = '*';
241 break;
242 case PROMPT_PAREN:
243 buf[0] = '(';
244 break;
245 default:
246 buf[0] = '0円';
247 break;
248 }
249 break;
250
251 case 'x':
252 if (!pset.db)
253 buf[0] = '?';
254 else
255 switch (PQtransactionStatus(pset.db))
256 {
257 case PQTRANS_IDLE:
258 buf[0] = '0円';
259 break;
260 case PQTRANS_ACTIVE:
261 case PQTRANS_INTRANS:
262 buf[0] = '*';
263 break;
264 case PQTRANS_INERROR:
265 buf[0] = '!';
266 break;
267 default:
268 buf[0] = '?';
269 break;
270 }
271 break;
272
273 case 'l':
275 break;
276
277 case '?':
278 /* not here yet */
279 break;
280
281 case '#':
282 if (is_superuser())
283 buf[0] = '#';
284 else
285 buf[0] = '>';
286 break;
287
288 /* execute command */
289 case '`':
290 {
291 int cmdend = strcspn(p + 1, "`");
292 char *file = pnstrdup(p + 1, cmdend);
293 FILE *fd;
294
295 fflush(NULL);
296 fd = popen(file, "r");
297 if (fd)
298 {
299 if (fgets(buf, sizeof(buf), fd) == NULL)
300 buf[0] = '0円';
301 pclose(fd);
302 }
303
304 /* strip trailing newline and carriage return */
305 (void) pg_strip_crlf(buf);
306
307 free(file);
308 p += cmdend + 1;
309 break;
310 }
311
312 /* interpolate variable */
313 case ':':
314 {
315 int nameend = strcspn(p + 1, ":");
316 char *name = pnstrdup(p + 1, nameend);
317 const char *val;
318
320 if (val)
321 strlcpy(buf, val, sizeof(buf));
322 free(name);
323 p += nameend + 1;
324 break;
325 }
326
327 case '[':
328 case ']':
329#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
330
331 /*
332 * readline >=4.0 undocumented feature: non-printing
333 * characters in prompt strings must be marked as such, in
334 * order to properly display the line during editing.
335 */
336 buf[0] = (*p == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
337 buf[1] = '0円';
338#endif /* USE_READLINE */
339 break;
340
341 default:
342 buf[0] = *p;
343 buf[1] = '0円';
344 break;
345 }
346 esc = false;
347 }
348 else if (*p == '%')
349 esc = true;
350 else
351 {
352 buf[0] = *p;
353 buf[1] = '0円';
354 esc = false;
355 }
356
357 if (!esc)
358 strlcat(destination, buf, sizeof(destination));
359 }
360
361 /* Compute the visible width of PROMPT1, for PROMPT2's %w */
362 if (prompt_string == pset.prompt1)
363 {
364 char *p = destination;
365 char *end = p + strlen(p);
366 bool visible = true;
367
368 last_prompt1_width = 0;
369 while (*p)
370 {
371#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
372 if (*p == RL_PROMPT_START_IGNORE)
373 {
374 visible = false;
375 ++p;
376 }
377 else if (*p == RL_PROMPT_END_IGNORE)
378 {
379 visible = true;
380 ++p;
381 }
382 else
383#endif
384 {
385 int chlen,
386 chwidth;
387
388 chlen = PQmblen(p, pset.encoding);
389 if (p + chlen > end)
390 break; /* Invalid string */
391
392 if (visible)
393 {
394 chwidth = PQdsplen(p, pset.encoding);
395
396 if (*p == '\n')
397 last_prompt1_width = 0;
398 else if (chwidth > 0)
399 last_prompt1_width += chwidth;
400 }
401
402 p += chlen;
403 }
404 }
405 }
406
407 return destination;
408}
const char * session_username(void)
Definition: common.c:2520
#define unconstify(underlying_type, expr)
Definition: c.h:1244
#define Min(x, y)
Definition: c.h:1003
#define UINT64_FORMAT
Definition: c.h:557
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7513
char * PQport(const PGconn *conn)
Definition: fe-connect.c:7582
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:7624
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:7546
int PQbackendPID(const PGconn *conn)
Definition: fe-connect.c:7715
char * PQuser(const PGconn *conn)
Definition: fe-connect.c:7521
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
Definition: fe-connect.c:7723
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1255
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1276
#define free(a)
Definition: header.h:65
long val
Definition: informix.c:689
@ PQTRANS_INTRANS
Definition: libpq-fe.h:149
@ PQTRANS_IDLE
Definition: libpq-fe.h:147
@ PQTRANS_ACTIVE
Definition: libpq-fe.h:148
@ PQTRANS_INERROR
Definition: libpq-fe.h:150
PGpipelineStatus
Definition: libpq-fe.h:186
@ PQ_PIPELINE_ABORTED
Definition: libpq-fe.h:189
@ PQ_PIPELINE_ON
Definition: libpq-fe.h:188
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1770
#define DEFAULT_PGSOCKET_DIR
static bool is_superuser(Archive *fout)
Definition: pg_dump.c:5040
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define MAX_PROMPT_SIZE
@ PROMPT_READY
Definition: psqlscan.h:41
@ PROMPT_COPY
Definition: psqlscan.h:48
@ PROMPT_PAREN
Definition: psqlscan.h:47
@ PROMPT_COMMENT
Definition: psqlscan.h:43
@ PROMPT_CONTINUE
Definition: psqlscan.h:42
@ PROMPT_SINGLEQUOTE
Definition: psqlscan.h:44
@ PROMPT_DOLLARQUOTE
Definition: psqlscan.h:46
@ PROMPT_DOUBLEQUOTE
Definition: psqlscan.h:45
PsqlSettings pset
Definition: startup.c:32
int pg_strip_crlf(char *str)
Definition: string.c:154
VariableSpace vars
Definition: settings.h:151
int encoding
Definition: settings.h:104
const char * prompt2
Definition: settings.h:182
const char * prompt3
Definition: settings.h:183
PGconn * db
Definition: settings.h:103
uint64 stmt_lineno
Definition: settings.h:145
bool singleline
Definition: settings.h:168
const char * prompt1
Definition: settings.h:181
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:73
const char * name

References buf, conditional_active(), _psqlSettings::db, DEFAULT_PGSOCKET_DIR, _psqlSettings::encoding, fd(), free, GetVariable(), is_superuser(), is_unixsock_path(), MAX_PROMPT_SIZE, Min, name, pg_strip_crlf(), pnstrdup(), PQ_PIPELINE_ABORTED, PQ_PIPELINE_ON, PQbackendPID(), PQdb(), PQdsplen(), PQhost(), PQmblen(), PQpipelineStatus(), PQport(), PQTRANS_ACTIVE, PQTRANS_IDLE, PQTRANS_INERROR, PQTRANS_INTRANS, PQtransactionStatus(), PQuser(), _psqlSettings::prompt1, _psqlSettings::prompt2, _psqlSettings::prompt3, PROMPT_COMMENT, PROMPT_CONTINUE, PROMPT_COPY, PROMPT_DOLLARQUOTE, PROMPT_DOUBLEQUOTE, PROMPT_PAREN, PROMPT_READY, PROMPT_SINGLEQUOTE, pset, session_username(), _psqlSettings::singleline, snprintf, _psqlSettings::stmt_lineno, strlcat(), strlcpy(), UINT64_FORMAT, unconstify, val, and _psqlSettings::vars.

Referenced by handleCopyIn(), and MainLoop().

AltStyle によって変換されたページ (->オリジナル) /