Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include "postgres_fe.h"
00009
00010 #ifdef WIN32
00011 #include <io.h>
00012 #include <win32.h>
00013 #endif
00014
00015 #ifdef HAVE_UNIX_SOCKETS
00016 #include <unistd.h>
00017 #include <netdb.h>
00018 #endif
00019
00020 #include "common.h"
00021 #include "input.h"
00022 #include "prompt.h"
00023 #include "settings.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 char *
00067 get_prompt(promptStatus_t status)
00068 {
00069 #define MAX_PROMPT_SIZE 256
00070 static char destination[MAX_PROMPT_SIZE + 1];
00071 char buf[MAX_PROMPT_SIZE + 1];
00072 bool esc = false;
00073 const char *p;
00074 const char *prompt_string = "? ";
00075
00076 switch (status)
00077 {
00078 case PROMPT_READY:
00079 prompt_string = pset.prompt1;
00080 break;
00081
00082 case PROMPT_CONTINUE:
00083 case PROMPT_SINGLEQUOTE:
00084 case PROMPT_DOUBLEQUOTE:
00085 case PROMPT_DOLLARQUOTE:
00086 case PROMPT_COMMENT:
00087 case PROMPT_PAREN:
00088 prompt_string = pset.prompt2;
00089 break;
00090
00091 case PROMPT_COPY:
00092 prompt_string = pset.prompt3;
00093 break;
00094 }
00095
00096 destination[0] = '\0';
00097
00098 for (p = prompt_string;
00099 *p && strlen(destination) < sizeof(destination) - 1;
00100 p++)
00101 {
00102 memset(buf, 0, sizeof(buf));
00103 if (esc)
00104 {
00105 switch (*p)
00106 {
00107
00108 case '/':
00109 if (pset.db)
00110 strlcpy(buf, PQdb(pset.db), sizeof(buf));
00111 break;
00112 case '~':
00113 if (pset.db)
00114 {
00115 const char *var;
00116
00117 if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
00118 ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
00119 strlcpy(buf, "~", sizeof(buf));
00120 else
00121 strlcpy(buf, PQdb(pset.db), sizeof(buf));
00122 }
00123 break;
00124
00125
00126 case 'M':
00127 case 'm':
00128 if (pset.db)
00129 {
00130 const char *host = PQhost(pset.db);
00131
00132
00133 if (host && host[0] && !is_absolute_path(host))
00134 {
00135 strlcpy(buf, host, sizeof(buf));
00136 if (*p == 'm')
00137 buf[strcspn(buf, ".")] = '\0';
00138 }
00139 #ifdef HAVE_UNIX_SOCKETS
00140
00141 else
00142 {
00143 if (!host
00144 || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0
00145 || *p == 'm')
00146 strlcpy(buf, "[local]", sizeof(buf));
00147 else
00148 snprintf(buf, sizeof(buf), "[local:%s]", host);
00149 }
00150 #endif
00151 }
00152 break;
00153
00154 case '>':
00155 if (pset.db && PQport(pset.db))
00156 strlcpy(buf, PQport(pset.db), sizeof(buf));
00157 break;
00158
00159 case 'n':
00160 if (pset.db)
00161 strlcpy(buf, session_username(), sizeof(buf));
00162 break;
00163
00164 case '0':
00165 case '1':
00166 case '2':
00167 case '3':
00168 case '4':
00169 case '5':
00170 case '6':
00171 case '7':
00172 *buf = (char) strtol(p, (char **) &p, 8);
00173 --p;
00174 break;
00175 case 'R':
00176 switch (status)
00177 {
00178 case PROMPT_READY:
00179 if (!pset.db)
00180 buf[0] = '!';
00181 else if (!pset.singleline)
00182 buf[0] = '=';
00183 else
00184 buf[0] = '^';
00185 break;
00186 case PROMPT_CONTINUE:
00187 buf[0] = '-';
00188 break;
00189 case PROMPT_SINGLEQUOTE:
00190 buf[0] = '\'';
00191 break;
00192 case PROMPT_DOUBLEQUOTE:
00193 buf[0] = '"';
00194 break;
00195 case PROMPT_DOLLARQUOTE:
00196 buf[0] = '$';
00197 break;
00198 case PROMPT_COMMENT:
00199 buf[0] = '*';
00200 break;
00201 case PROMPT_PAREN:
00202 buf[0] = '(';
00203 break;
00204 default:
00205 buf[0] = '\0';
00206 break;
00207 }
00208 break;
00209
00210 case 'x':
00211 if (!pset.db)
00212 buf[0] = '?';
00213 else
00214 switch (PQtransactionStatus(pset.db))
00215 {
00216 case PQTRANS_IDLE:
00217 buf[0] = '\0';
00218 break;
00219 case PQTRANS_ACTIVE:
00220 case PQTRANS_INTRANS:
00221 buf[0] = '*';
00222 break;
00223 case PQTRANS_INERROR:
00224 buf[0] = '!';
00225 break;
00226 default:
00227 buf[0] = '?';
00228 break;
00229 }
00230 break;
00231
00232 case '?':
00233
00234 break;
00235
00236 case '#':
00237 if (is_superuser())
00238 buf[0] = '#';
00239 else
00240 buf[0] = '>';
00241 break;
00242
00243
00244 case '`':
00245 {
00246 FILE *fd;
00247 char *file = pg_strdup(p + 1);
00248 int cmdend;
00249
00250 cmdend = strcspn(file, "`");
00251 file[cmdend] = '\0';
00252 fd = popen(file, "r");
00253 if (fd)
00254 {
00255 if (fgets(buf, sizeof(buf), fd) == NULL)
00256 buf[0] = '\0';
00257 pclose(fd);
00258 }
00259 if (strlen(buf) > 0 && buf[strlen(buf) - 1] == '\n')
00260 buf[strlen(buf) - 1] = '\0';
00261 free(file);
00262 p += cmdend + 1;
00263 break;
00264 }
00265
00266
00267 case ':':
00268 {
00269 char *name;
00270 const char *val;
00271 int nameend;
00272
00273 name = pg_strdup(p + 1);
00274 nameend = strcspn(name, ":");
00275 name[nameend] = '\0';
00276 val = GetVariable(pset.vars, name);
00277 if (val)
00278 strlcpy(buf, val, sizeof(buf));
00279 free(name);
00280 p += nameend + 1;
00281 break;
00282 }
00283
00284 case '[':
00285 case ']':
00286 #if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE)
00287
00288
00289
00290
00291
00292
00293 buf[0] = (*p == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
00294 buf[1] = '\0';
00295 #endif
00296 break;
00297
00298 default:
00299 buf[0] = *p;
00300 buf[1] = '\0';
00301 break;
00302
00303 }
00304 esc = false;
00305 }
00306 else if (*p == '%')
00307 esc = true;
00308 else
00309 {
00310 buf[0] = *p;
00311 buf[1] = '\0';
00312 esc = false;
00313 }
00314
00315 if (!esc)
00316 strlcat(destination, buf, sizeof(destination));
00317 }
00318
00319 return destination;
00320 }