PostgreSQL Source Code  git master
prompt.c File Reference
#include "postgres_fe.h"
#include "common.h"
#include "input.h"
#include "prompt.h"
#include "settings.h"
#include "common/string.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

Referenced by get_prompt().

Function Documentation

◆ get_prompt()

char* get_prompt ( promptStatus_t  status,
ConditionalStack  cstack 
)

Definition at line 70 of file prompt.c.

References buf, conditional_active(), _psqlSettings::db, DEFAULT_PGSOCKET_DIR, fd(), free, GetVariable(), is_absolute_path, is_superuser(), MAX_PROMPT_SIZE, name, pg_strdup(), pg_strip_crlf(), PQbackendPID(), PQdb(), PQhost(), 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().

71 {
72 #define MAX_PROMPT_SIZE 256
73  static char destination[MAX_PROMPT_SIZE + 1];
74  char buf[MAX_PROMPT_SIZE + 1];
75  bool esc = false;
76  const char *p;
77  const char *prompt_string = "? ";
78 
79  switch (status)
80  {
81  case PROMPT_READY:
82  prompt_string = pset.prompt1;
83  break;
84 
85  case PROMPT_CONTINUE:
86  case PROMPT_SINGLEQUOTE:
87  case PROMPT_DOUBLEQUOTE:
88  case PROMPT_DOLLARQUOTE:
89  case PROMPT_COMMENT:
90  case PROMPT_PAREN:
91  prompt_string = pset.prompt2;
92  break;
93 
94  case PROMPT_COPY:
95  prompt_string = pset.prompt3;
96  break;
97  }
98 
99  destination[0] = '\0';
100 
101  for (p = prompt_string;
102  *p && strlen(destination) < sizeof(destination) - 1;
103  p++)
104  {
105  memset(buf, 0, sizeof(buf));
106  if (esc)
107  {
108  switch (*p)
109  {
110  /* Current database */
111  case '/':
112  if (pset.db)
113  strlcpy(buf, PQdb(pset.db), sizeof(buf));
114  break;
115  case '~':
116  if (pset.db)
117  {
118  const char *var;
119 
120  if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
121  ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
122  strlcpy(buf, "~", sizeof(buf));
123  else
124  strlcpy(buf, PQdb(pset.db), sizeof(buf));
125  }
126  break;
127 
128  /* DB server hostname (long/short) */
129  case 'M':
130  case 'm':
131  if (pset.db)
132  {
133  const char *host = PQhost(pset.db);
134 
135  /* INET socket */
136  if (host && host[0] && !is_absolute_path(host))
137  {
138  strlcpy(buf, host, sizeof(buf));
139  if (*p == 'm')
140  buf[strcspn(buf, ".")] = '\0';
141  }
142 #ifdef HAVE_UNIX_SOCKETS
143  /* UNIX socket */
144  else
145  {
146  if (!host
147  || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0
148  || *p == 'm')
149  strlcpy(buf, "[local]", sizeof(buf));
150  else
151  snprintf(buf, sizeof(buf), "[local:%s]", host);
152  }
153 #endif
154  }
155  break;
156  /* DB server port number */
157  case '>':
158  if (pset.db && PQport(pset.db))
159  strlcpy(buf, PQport(pset.db), sizeof(buf));
160  break;
161  /* DB server user name */
162  case 'n':
163  if (pset.db)
164  strlcpy(buf, session_username(), sizeof(buf));
165  break;
166  /* backend pid */
167  case 'p':
168  if (pset.db)
169  {
170  int pid = PQbackendPID(pset.db);
171 
172  if (pid)
173  snprintf(buf, sizeof(buf), "%d", pid);
174  }
175  break;
176 
177  case '0':
178  case '1':
179  case '2':
180  case '3':
181  case '4':
182  case '5':
183  case '6':
184  case '7':
185  *buf = (char) strtol(p, unconstify(char **, &p), 8);
186  --p;
187  break;
188  case 'R':
189  switch (status)
190  {
191  case PROMPT_READY:
192  if (cstack != NULL && !conditional_active(cstack))
193  buf[0] = '@';
194  else if (!pset.db)
195  buf[0] = '!';
196  else if (!pset.singleline)
197  buf[0] = '=';
198  else
199  buf[0] = '^';
200  break;
201  case PROMPT_CONTINUE:
202  buf[0] = '-';
203  break;
204  case PROMPT_SINGLEQUOTE:
205  buf[0] = '\'';
206  break;
207  case PROMPT_DOUBLEQUOTE:
208  buf[0] = '"';
209  break;
210  case PROMPT_DOLLARQUOTE:
211  buf[0] = '$';
212  break;
213  case PROMPT_COMMENT:
214  buf[0] = '*';
215  break;
216  case PROMPT_PAREN:
217  buf[0] = '(';
218  break;
219  default:
220  buf[0] = '\0';
221  break;
222  }
223  break;
224 
225  case 'x':
226  if (!pset.db)
227  buf[0] = '?';
228  else
229  switch (PQtransactionStatus(pset.db))
230  {
231  case PQTRANS_IDLE:
232  buf[0] = '\0';
233  break;
234  case PQTRANS_ACTIVE:
235  case PQTRANS_INTRANS:
236  buf[0] = '*';
237  break;
238  case PQTRANS_INERROR:
239  buf[0] = '!';
240  break;
241  default:
242  buf[0] = '?';
243  break;
244  }
245  break;
246 
247  case 'l':
248  snprintf(buf, sizeof(buf), UINT64_FORMAT, pset.stmt_lineno);
249  break;
250 
251  case '?':
252  /* not here yet */
253  break;
254 
255  case '#':
256  if (is_superuser())
257  buf[0] = '#';
258  else
259  buf[0] = '>';
260  break;
261 
262  /* execute command */
263  case '`':
264  {
265  FILE *fd;
266  char *file = pg_strdup(p + 1);
267  int cmdend;
268 
269  cmdend = strcspn(file, "`");
270  file[cmdend] = '\0';
271  fd = popen(file, "r");
272  if (fd)
273  {
274  if (fgets(buf, sizeof(buf), fd) == NULL)
275  buf[0] = '\0';
276  pclose(fd);
277  }
278 
279  /* strip trailing newline and carriage return */
280  (void) pg_strip_crlf(buf);
281 
282  free(file);
283  p += cmdend + 1;
284  break;
285  }
286 
287  /* interpolate variable */
288  case ':':
289  {
290  char *name;
291  const char *val;
292  int nameend;
293 
294  name = pg_strdup(p + 1);
295  nameend = strcspn(name, ":");
296  name[nameend] = '\0';
297  val = GetVariable(pset.vars, name);
298  if (val)
299  strlcpy(buf, val, sizeof(buf));
300  free(name);
301  p += nameend + 1;
302  break;
303  }
304 
305  case '[':
306  case ']':
307 #if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
308 
309  /*
310  * readline >=4.0 undocumented feature: non-printing
311  * characters in prompt strings must be marked as such, in
312  * order to properly display the line during editing.
313  */
314  buf[0] = (*p == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
315  buf[1] = '\0';
316 #endif /* USE_READLINE */
317  break;
318 
319  default:
320  buf[0] = *p;
321  buf[1] = '\0';
322  break;
323 
324  }
325  esc = false;
326  }
327  else if (*p == '%')
328  esc = true;
329  else
330  {
331  buf[0] = *p;
332  buf[1] = '\0';
333  esc = false;
334  }
335 
336  if (!esc)
337  strlcat(destination, buf, sizeof(destination));
338  }
339 
340  return destination;
341 }
PGconn * db
Definition: settings.h:83
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:128
PsqlSettings pset
Definition: startup.c:35
int pg_strip_crlf(char *str)
Definition: string.c:105
const char * prompt3
Definition: settings.h:141
char * PQport(const PGconn *conn)
Definition: fe-connect.c:6515
static int fd(const char *x, int i)
Definition: preproc-init.c:105
char * PQuser(const PGconn *conn)
Definition: fe-connect.c:6454
static char * buf
Definition: pg_test_fsync.c:68
const char * session_username(void)
Definition: common.c:2336
#define is_absolute_path(filename)
Definition: port.h:86
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool singleline
Definition: settings.h:128
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6551
#define unconstify(underlying_type, expr)
Definition: c.h:1163
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:73
int PQbackendPID(const PGconn *conn)
Definition: fe-connect.c:6622
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:6479
#define free(a)
Definition: header.h:65
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6446
#define MAX_PROMPT_SIZE
const char * prompt2
Definition: settings.h:140
const char * prompt1
Definition: settings.h:139
static bool is_superuser(Archive *fout)
Definition: pg_dump.c:4080
const char * name
Definition: encode.c:521
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define snprintf
Definition: port.h:192
#define UINT64_FORMAT
Definition: c.h:401
long val
Definition: informix.c:684
uint64 stmt_lineno
Definition: settings.h:112
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:33
#define DEFAULT_PGSOCKET_DIR
VariableSpace vars
Definition: settings.h:118