PostgreSQL Source Code git master
Loading...
Searching...
No Matches
prompt.h File Reference
Include dependency graph for prompt.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

charget_prompt (promptStatus_t status, ConditionalStack cstack)
 

Function Documentation

◆ get_prompt()

char * get_prompt ( promptStatus_t  status,
ConditionalStack  cstack 
)

Definition at line 71 of file prompt.c.

72{
73#define MAX_PROMPT_SIZE 256
74 static char destination[MAX_PROMPT_SIZE + 1];
75 char buf[MAX_PROMPT_SIZE + 1];
76 bool esc = false;
77 const char *p;
78 const char *prompt_string = "? ";
79 static size_t last_prompt1_width = 0;
80
81 switch (status)
82 {
83 case PROMPT_READY:
85 break;
86
87 case PROMPT_CONTINUE:
91 case PROMPT_COMMENT:
92 case PROMPT_PAREN:
94 break;
95
96 case PROMPT_COPY:
98 break;
99 }
100
101 destination[0] = '\0';
102
103 for (p = prompt_string;
104 *p && strlen(destination) < sizeof(destination) - 1;
105 p++)
106 {
107 memset(buf, 0, sizeof(buf));
108 if (esc)
109 {
110 switch (*p)
111 {
112 /* Current database */
113 case '/':
114 if (pset.db)
115 strlcpy(buf, PQdb(pset.db), sizeof(buf));
116 break;
117 case '~':
118 if (pset.db)
119 {
120 const char *var;
121
122 if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
123 ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
124 strlcpy(buf, "~", sizeof(buf));
125 else
126 strlcpy(buf, PQdb(pset.db), sizeof(buf));
127 }
128 break;
129
130 /* Whitespace of the same width as the last PROMPT1 */
131 case 'w':
132 if (pset.db)
133 memset(buf, ' ',
134 Min(last_prompt1_width, sizeof(buf) - 1));
135 break;
136
137 /* DB server hostname (long/short) */
138 case 'M':
139 case 'm':
140 if (pset.db)
141 {
142 const char *host = PQhost(pset.db);
143
144 /* INET socket */
145 if (host && host[0] && !is_unixsock_path(host))
146 {
147 strlcpy(buf, host, sizeof(buf));
148 if (*p == 'm')
149 buf[strcspn(buf, ".")] = '\0';
150 }
151 /* UNIX socket */
152 else
153 {
154 if (!host
155 || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0
156 || *p == 'm')
157 strlcpy(buf, "[local]", sizeof(buf));
158 else
159 snprintf(buf, sizeof(buf), "[local:%s]", host);
160 }
161 }
162 break;
163 /* DB server port number */
164 case '>':
165 if (pset.db && PQport(pset.db))
166 strlcpy(buf, PQport(pset.db), sizeof(buf));
167 break;
168 /* DB server user name */
169 case 'n':
170 if (pset.db)
171 strlcpy(buf, session_username(), sizeof(buf));
172 break;
173 /* search_path */
174 case 'S':
175 if (pset.db)
176 {
177 const char *sp = PQparameterStatus(pset.db, "search_path");
178
179 /* Use ? for versions that don't report search_path. */
180 strlcpy(buf, sp ? sp : "?", sizeof(buf));
181 }
182 break;
183 /* service name */
184 case 's':
185 {
186 const char *service_name = GetVariable(pset.vars, "SERVICE");
187
188 if (service_name)
189 strlcpy(buf, service_name, sizeof(buf));
190 }
191 break;
192 /* backend pid */
193 case 'p':
194 if (pset.db)
195 {
196 int pid = PQbackendPID(pset.db);
197
198 if (pid)
199 snprintf(buf, sizeof(buf), "%d", pid);
200 }
201 break;
202 /* pipeline status */
203 case 'P':
204 if (pset.db)
205 {
207
208 if (status == PQ_PIPELINE_ON)
209 strlcpy(buf, "on", sizeof(buf));
210 else if (status == PQ_PIPELINE_ABORTED)
211 strlcpy(buf, "abort", sizeof(buf));
212 else
213 strlcpy(buf, "off", sizeof(buf));
214 }
215 break;
216 case '0':
217 case '1':
218 case '2':
219 case '3':
220 case '4':
221 case '5':
222 case '6':
223 case '7':
224 *buf = (char) strtol(p, unconstify(char **, &p), 8);
225 --p;
226 break;
227 case 'R':
228 switch (status)
229 {
230 case PROMPT_READY:
231 if (cstack != NULL && !conditional_active(cstack))
232 buf[0] = '@';
233 else if (!pset.db)
234 buf[0] = '!';
235 else if (!pset.singleline)
236 buf[0] = '=';
237 else
238 buf[0] = '^';
239 break;
240 case PROMPT_CONTINUE:
241 buf[0] = '-';
242 break;
244 buf[0] = '\'';
245 break;
247 buf[0] = '"';
248 break;
250 buf[0] = '$';
251 break;
252 case PROMPT_COMMENT:
253 buf[0] = '*';
254 break;
255 case PROMPT_PAREN:
256 buf[0] = '(';
257 break;
258 default:
259 buf[0] = '\0';
260 break;
261 }
262 break;
263 case 'i':
264 if (pset.db)
265 {
266 const char *hs = PQparameterStatus(pset.db, "in_hot_standby");
267
268 if (hs)
269 {
270 if (strcmp(hs, "on") == 0)
271 strlcpy(buf, "standby", sizeof(buf));
272 else
273 strlcpy(buf, "primary", sizeof(buf));
274 }
275 /* Use ? for versions that don't report in_hot_standby */
276 else
277 buf[0] = '?';
278 }
279 break;
280 case 'x':
281 if (!pset.db)
282 buf[0] = '?';
283 else
284 switch (PQtransactionStatus(pset.db))
285 {
286 case PQTRANS_IDLE:
287 buf[0] = '\0';
288 break;
289 case PQTRANS_ACTIVE:
290 case PQTRANS_INTRANS:
291 buf[0] = '*';
292 break;
293 case PQTRANS_INERROR:
294 buf[0] = '!';
295 break;
296 default:
297 buf[0] = '?';
298 break;
299 }
300 break;
301
302 case 'l':
304 break;
305
306 case '?':
307 /* not here yet */
308 break;
309
310 case '#':
311 if (is_superuser())
312 buf[0] = '#';
313 else
314 buf[0] = '>';
315 break;
316
317 /* execute command */
318 case '`':
319 {
320 int cmdend = strcspn(p + 1, "`");
321 char *file = pnstrdup(p + 1, cmdend);
322 FILE *fd;
323
324 fflush(NULL);
325 fd = popen(file, "r");
326 if (fd)
327 {
328 if (fgets(buf, sizeof(buf), fd) == NULL)
329 buf[0] = '\0';
330 pclose(fd);
331 }
332
333 /* strip trailing newline and carriage return */
335
336 free(file);
337 p += cmdend + 1;
338 break;
339 }
340
341 /* interpolate variable */
342 case ':':
343 {
344 int nameend = strcspn(p + 1, ":");
345 char *name = pnstrdup(p + 1, nameend);
346 const char *val;
347
349 if (val)
350 strlcpy(buf, val, sizeof(buf));
351 free(name);
352 p += nameend + 1;
353 break;
354 }
355
356 case '[':
357 case ']':
358#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
359
360 /*
361 * readline >=4.0 undocumented feature: non-printing
362 * characters in prompt strings must be marked as such, in
363 * order to properly display the line during editing.
364 */
366 buf[1] = '\0';
367#endif /* USE_READLINE */
368 break;
369
370 default:
371 buf[0] = *p;
372 buf[1] = '\0';
373 break;
374 }
375 esc = false;
376 }
377 else if (*p == '%')
378 esc = true;
379 else
380 {
381 buf[0] = *p;
382 buf[1] = '\0';
383 esc = false;
384 }
385
386 if (!esc)
388 }
389
390 /* Compute the visible width of PROMPT1, for PROMPT2's %w */
392 {
393 char *p = destination;
394 char *end = p + strlen(p);
395 bool visible = true;
396
398 while (*p)
399 {
400#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
401 if (*p == RL_PROMPT_START_IGNORE)
402 {
403 visible = false;
404 ++p;
405 }
406 else if (*p == RL_PROMPT_END_IGNORE)
407 {
408 visible = true;
409 ++p;
410 }
411 else
412#endif
413 {
414 int chlen,
415 chwidth;
416
418 if (p + chlen > end)
419 break; /* Invalid string */
420
421 if (visible)
422 {
424
425 if (*p == '\n')
427 else if (chwidth > 0)
429 }
430
431 p += chlen;
432 }
433 }
434 }
435
436 return destination;
437}
const char * session_username(void)
Definition common.c:2520
bool is_superuser(void)
Definition common.c:2480
#define unconstify(underlying_type, expr)
Definition c.h:1240
#define Min(x, y)
Definition c.h:997
#define UINT64_FORMAT
Definition c.h:565
bool conditional_active(ConditionalStack cstack)
char * PQdb(const PGconn *conn)
char * PQport(const PGconn *conn)
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
char * PQhost(const PGconn *conn)
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
int PQbackendPID(const PGconn *conn)
char * PQuser(const PGconn *conn)
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
int PQmblen(const char *s, int encoding)
Definition fe-misc.c:1255
int PQdsplen(const char *s, int encoding)
Definition fe-misc.c:1276
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:1792
#define DEFAULT_PGSOCKET_DIR
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
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:66
static int fd(const char *x, int i)
static int fb(int x)
#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
#define free(a)
int pg_strip_crlf(char *str)
Definition string.c:154
VariableSpace vars
Definition settings.h:151
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, fb(), 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(), PQparameterStatus(), 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().