2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2025, PostgreSQL Global Development Group
6 * src/bin/psql/prompt.c
22/*--------------------------
25 * Returns a statically allocated prompt made by interpolating certain
26 * tcsh style escape sequences into pset.vars "PROMPT1|2|3".
27 * (might not be completely multibyte safe)
29 * Defined interpolations are:
30 * %M - database server "hostname.domainname", "[local]" for AF_UNIX
31 * sockets, "[local:/dir/name]" if not default
32 * %m - like %M, but hostname only (before first dot), or always "[local]"
34 * %P - pipeline status: on, off or abort
35 * %> - database server port number
36 * %n - database user name
38 * %/ - current database
39 * %~ - like %/ but "~" when database name equals user name
40 * %w - whitespace of the same width as the most recent output of PROMPT1
41 * %# - "#" if superuser, ">" otherwise
42 * %R - in prompt1 normally =, or ^ if single line mode,
43 * or a ! if session is not connected to a database;
44 * in prompt2 -, *, ', or ";
46 * %x - transaction status: empty, *, !, ? (unknown or no connection)
47 * %l - The line number inside the current statement, starting from 1.
48 * %? - the error code of the last query (not yet implemented)
51 * %[0-9] - the character with the given decimal code
52 * %0[0-7] - the character with the given octal code
53 * %0x[0-9A-Fa-f] - the character with the given hexadecimal code
55 * %`command` - The result of executing command in /bin/sh with trailing
57 * %:name: - The value of the psql variable 'name'
58 * (those will not be rescanned for more escape sequences!)
60 * %[ ... %] - tell readline that the contained text is invisible
62 * If the application-wide prompts become NULL somehow, the returned string
63 * will be empty (not NULL!).
64 *--------------------------
70#define MAX_PROMPT_SIZE 256
75 const char *prompt_string =
"? ";
76 static size_t last_prompt1_width = 0;
98 destination[0] =
'0円';
100 for (p = prompt_string;
101 *p && strlen(destination) <
sizeof(destination) - 1;
104 memset(
buf, 0,
sizeof(
buf));
109 /* Current database */
120 ((var = getenv(
"PGDATABASE")) && strcmp(var,
PQdb(
pset.
db)) == 0))
127 /* Whitespace of the same width as the last PROMPT1 */
131 Min(last_prompt1_width,
sizeof(
buf) - 1));
134 /* DB server hostname (long/short) */
146 buf[strcspn(
buf,
".")] =
'0円';
160 /* DB server port number */
165 /* DB server user name */
189 /* pipeline status */
288 /* execute command */
291 int cmdend = strcspn(p + 1,
"`");
292 char *file =
pnstrdup(p + 1, cmdend);
296 fd = popen(file,
"r");
299 if (fgets(
buf,
sizeof(
buf),
fd) == NULL)
304 /* strip trailing newline and carriage return */
312 /* interpolate variable */
315 int nameend = strcspn(p + 1,
":");
329#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
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.
336 buf[0] = (*p ==
'[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
338#endif /* USE_READLINE */
358 strlcat(destination,
buf,
sizeof(destination));
361 /* Compute the visible width of PROMPT1, for PROMPT2's %w */
364 char *p = destination;
365 char *end = p + strlen(p);
368 last_prompt1_width = 0;
371#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
372 if (*p == RL_PROMPT_START_IGNORE)
377 else if (*p == RL_PROMPT_END_IGNORE)
390 break;
/* Invalid string */
397 last_prompt1_width = 0;
398 else if (chwidth > 0)
399 last_prompt1_width += chwidth;
const char * session_username(void)
#define unconstify(underlying_type, expr)
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)
int PQbackendPID(const PGconn *conn)
char * PQuser(const PGconn *conn)
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
int PQmblen(const char *s, int encoding)
int PQdsplen(const char *s, int encoding)
char * pnstrdup(const char *in, Size len)
#define DEFAULT_PGSOCKET_DIR
static bool is_superuser(Archive *fout)
size_t strlcat(char *dst, const char *src, size_t siz)
size_t strlcpy(char *dst, const char *src, size_t siz)
static bool is_unixsock_path(const char *path)
static int fd(const char *x, int i)
char * get_prompt(promptStatus_t status, ConditionalStack cstack)
enum _promptStatus promptStatus_t
int pg_strip_crlf(char *str)
const char * GetVariable(VariableSpace space, const char *name)