2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2008, PostgreSQL Global Development Group
8 #include "postgres_fe.h"
15 #ifdef HAVE_UNIX_SOCKETS
26 /*--------------------------
29 * Returns a statically allocated prompt made by interpolating certain
30 * tcsh style escape sequences into pset.vars "PROMPT1|2|3".
31 * (might not be completely multibyte safe)
33 * Defined interpolations are:
34 * %M - database server "hostname.domainname", "[local]" for AF_UNIX
35 * sockets, "[local:/dir/name]" if not default
36 * %m - like %M, but hostname only (before first dot), or always "[local]"
37 * %> - database server port number
38 * %n - database user name
39 * %/ - current database
40 * %~ - like %/ but "~" when database name equals user name
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 * %? - the error code of the last query (not yet implemented)
50 * %[0-9] - the character with the given decimal code
51 * %0[0-7] - the character with the given octal code
52 * %0x[0-9A-Fa-f] - the character with the given hexadecimal code
54 * %`command` - The result of executing command in /bin/sh with trailing
56 * %:name: - The value of the psql variable 'name'
57 * (those will not be rescanned for more escape sequences!)
59 * %[ ... %] - tell readline that the contained text is invisible
61 * If the application-wide prompts become NULL somehow, the returned string
62 * will be empty (not NULL!).
63 *--------------------------
67 get_prompt(promptStatus_t status
)
69 #define MAX_PROMPT_SIZE 256
70 static char destination
[MAX_PROMPT_SIZE
+ 1];
71 char buf
[MAX_PROMPT_SIZE
+ 1];
74 const char *prompt_string
= "? ";
79 prompt_string
= pset
.prompt1
;
83 case PROMPT_SINGLEQUOTE
:
84 case PROMPT_DOUBLEQUOTE
:
85 case PROMPT_DOLLARQUOTE
:
88 prompt_string
= pset
.prompt2
;
92 prompt_string
= pset
.prompt3
;
96 destination
[0] = '\0';
98 for (p
= prompt_string
;
99 *p
&& strlen(destination
) < sizeof(destination
) - 1;
102 memset(buf
, 0, sizeof(buf
));
107 /* Current database */
110 strlcpy(buf
, PQdb(pset
.db
), sizeof(buf
));
117 if (strcmp(PQdb(pset
.db
), PQuser(pset
.db
)) == 0 ||
118 ((var
= getenv("PGDATABASE")) && strcmp(var
, PQdb(pset
.db
)) == 0))
119 strlcpy(buf
, "~", sizeof(buf
));
121 strlcpy(buf
, PQdb(pset
.db
), sizeof(buf
));
125 /* DB server hostname (long/short) */
130 const char *host
= PQhost(pset
.db
);
133 if (host
&& host
[0] && !is_absolute_path(host
))
135 strlcpy(buf
, host
, sizeof(buf
));
137 buf
[strcspn(buf
, ".")] = '\0';
139 #ifdef HAVE_UNIX_SOCKETS
144 || strcmp(host
, DEFAULT_PGSOCKET_DIR
) == 0
146 strlcpy(buf
, "[local]", sizeof(buf
));
148 snprintf(buf
, sizeof(buf
), "[local:%s]", host
);
153 /* DB server port number */
155 if (pset
.db
&& PQport(pset
.db
))
156 strlcpy(buf
, PQport(pset
.db
), sizeof(buf
));
158 /* DB server user name */
161 strlcpy(buf
, session_username(), sizeof(buf
));
172 *buf
= (char) strtol(p
, (char **) &p
, 8);
181 else if (!pset
.singleline
)
186 case PROMPT_CONTINUE
:
189 case PROMPT_SINGLEQUOTE
:
192 case PROMPT_DOUBLEQUOTE
:
195 case PROMPT_DOLLARQUOTE
:
214 switch (PQtransactionStatus(pset
.db
))
220 case PQTRANS_INTRANS
:
223 case PQTRANS_INERROR
:
243 /* execute command */
247 char *file
= pg_strdup(p
+ 1);
250 cmdend
= strcspn(file
, "`");
252 fd
= popen(file
, "r");
255 fgets(buf
, sizeof(buf
), fd
);
258 if (strlen(buf
) > 0 && buf
[strlen(buf
) - 1] == '\n')
259 buf
[strlen(buf
) - 1] = '\0';
265 /* interpolate variable */
272 name
= pg_strdup(p
+ 1);
273 nameend
= strcspn(name
, ":");
274 name
[nameend
] = '\0';
275 val
= GetVariable(pset
.vars
, name
);
277 strlcpy(buf
, val
, sizeof(buf
));
285 #if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
288 * readline >=4.0 undocumented feature: non-printing
289 * characters in prompt strings must be marked as such, in
290 * order to properly display the line during editing.
292 buf
[0] = (*p
== '[') ? RL_PROMPT_START_IGNORE
: RL_PROMPT_END_IGNORE
;
294 #endif /* USE_READLINE */
315 strlcat(destination
, buf
, sizeof(destination
));