2 * psql - the PostgreSQL interactive terminal
4 * Copyright 2000-2002 by PostgreSQL Global Development Group
6 * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.86 2002/12/12 21:02:21 momjian Exp $
8 #include "postgres_fe.h"
18 #include <sys/types.h> /* for umask() */
19 #include <sys/stat.h> /* for stat() */
20 #include <fcntl.h> /* open() flags */
21 #include <unistd.h> /* for geteuid(), getpid(), stat() */
30 #include "pqexpbuffer.h"
37 #include "large_obj.h"
41 #include "variables.h"
42 #include "mb/pg_wchar.h"
44 /* functions for use in this file */
46 static backslashResult exec_command(const char *cmd,
47 const char *options_string,
48 const char **continue_parse,
49 PQExpBuffer query_buf,
50 volatile int *paren_level);
52 /* different ways for scan_option to handle parameter words */
55 OT_NORMAL, /* normal case */
56 OT_SQLID, /* treat as SQL identifier */
57 OT_SQLIDHACK, /* SQL identifier, but don't downcase */
58 OT_FILEPIPE /* it's a filename or pipe */
61 static char *scan_option(char **string, enum option_type type,
62 char *quote, bool semicolon);
63 static char *unescape(const unsigned char *source, size_t len);
65 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
66 static bool do_connect(const char *new_dbname, const char *new_user);
67 static bool do_shell(const char *command);
74 * Handles all the different commands that start with '\',
75 * ordinarily called by MainLoop().
77 * 'line' is the current input line, which should not start with a '\'
78 * but with the actual command name
79 * (that is taken care of by MainLoop)
81 * 'query_buf' contains the query-so-far, which may be modified by
82 * execution of the backslash command (for example, \r clears it)
83 * query_buf can be NULL if there is no query so far.
85 * Returns a status code indicating what action is desired, see command.h.
90 HandleSlashCmds(const char *line,
91 PQExpBuffer query_buf,
92 const char **end_of_cmd,
93 volatile int *paren_level)
95 backslashResult status = CMD_SKIP_LINE;
97 char *options_string = NULL;
99 const char *continue_parse = NULL; /* tell the mainloop where the
100 * backslash command ended */
102 #ifdef USE_ASSERT_CHECKING
106 my_line = xstrdup(line);
109 * Find the first whitespace. line[blank_loc] will now be the
110 * whitespace character or the \0 at the end
112 * Also look for a backslash, so stuff like \p\g works.
114 blank_loc = strcspn(my_line, " \t\n\r\\");
116 if (my_line[blank_loc] == '\\')
118 continue_parse = &my_line[blank_loc];
119 my_line[blank_loc] = '\0';
120 /* If it's a double backslash, we skip it. */
121 if (my_line[blank_loc + 1] == '\\')
124 /* do we have an option string? */
125 else if (my_line[blank_loc] != '\0')
127 options_string = &my_line[blank_loc + 1];
128 my_line[blank_loc] = '\0';
131 status = exec_command(my_line, options_string, &continue_parse, query_buf, paren_level);
133 if (status == CMD_UNKNOWN)
136 * If the command was not recognized, try to parse it as a
137 * one-letter command with immediately following argument (a
138 * still-supported, but no longer encouraged, syntax).
142 new_cmd[0] = my_line[0];
145 /* use line for options, because my_line was clobbered above */
146 status = exec_command(new_cmd, line + 1, &continue_parse, query_buf, paren_level);
149 * continue_parse must be relative to my_line for calculation
152 continue_parse += my_line - line;
154 #if 0 /* turned out to be too annoying */
155 if (status != CMD_UNKNOWN && isalpha((unsigned char) new_cmd[0]))
156 psql_error("Warning: This syntax is deprecated.\n");
160 if (status == CMD_UNKNOWN)
162 if (pset.cur_cmd_interactive)
163 fprintf(stderr, gettext("Invalid command \\%s. Try \\? for help.\n"), my_line);
165 psql_error("invalid command \\%s\n", my_line);
169 if (continue_parse && *continue_parse && *(continue_parse + 1) == '\\')
175 *end_of_cmd = line + (continue_parse - my_line);
177 *end_of_cmd = line + strlen(line);
187 static backslashResult
188 exec_command(const char *cmd,
189 const char *options_string,
190 const char **continue_parse,
191 PQExpBuffer query_buf,
192 volatile int *paren_level)
194 bool success = true; /* indicate here if the command ran ok or
196 bool quiet = QUIET();
197 backslashResult status = CMD_SKIP_LINE;
203 * The 'string' variable will be overwritten to point to the next
204 * token, hence we need an extra pointer so we can free this at the
208 string = string_cpy = xstrdup(options_string);
210 string = string_cpy = NULL;
213 * \a -- toggle field alignment This makes little sense but we keep it
216 if (strcmp(cmd, "a") == 0)
218 if (pset.popt.topt.format != PRINT_ALIGNED)
219 success = do_pset("format", "aligned", &pset.popt, quiet);
221 success = do_pset("format", "unaligned", &pset.popt, quiet);
224 /* \C -- override table title (formerly change HTML caption) */
225 else if (strcmp(cmd, "C") == 0)
227 char *opt = scan_option(&string, OT_NORMAL, NULL, true);
229 success = do_pset("title", opt, &pset.popt, quiet);
234 * \c or \connect -- connect to new database or as different user
236 * \c foo bar connect to db "foo" as user "bar"
237 * \c foo [-] connect to db "foo" as current user
238 * \c - bar connect to current db as user "bar"
239 * \c connect to default db as default user
242 else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
250 * Ideally we should treat the arguments as SQL identifiers. But
251 * for backwards compatibility with 7.2 and older pg_dump files,
252 * we have to take unquoted arguments verbatim (don't downcase
253 * them). For now, double-quoted arguments may be stripped of
254 * double quotes (as if SQL identifiers). By 7.4 or so, pg_dump
255 * files can be expected to double-quote all mixed-case \connect
256 * arguments, and then we can get rid of OT_SQLIDHACK.
258 opt1 = scan_option(&string, OT_SQLIDHACK, &opt1q, true);
259 opt2 = scan_option(&string, OT_SQLIDHACK, &opt2q, true);
263 success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
264 !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2);
266 /* gave database name */
267 success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1, "");
269 /* connect to default db as default user */
270 success = do_connect(NULL, NULL);
277 else if (strcmp(cmd, "cd") == 0)
279 char *opt = scan_option(&string, OT_NORMAL, NULL, true);
289 pw = getpwuid(geteuid());
292 psql_error("could not get home directory: %s\n", strerror(errno));
299 * On Windows, 'cd' without arguments prints the current
300 * directory, so if someone wants to code this here instead...
306 if (chdir(dir) == -1)
308 psql_error("\\%s: could not change directory to '%s': %s\n",
309 cmd, dir, strerror(errno));
318 else if (strcasecmp(cmd, "copy") == 0)
320 success = do_copy(options_string);
322 string += strlen(string);
326 else if (strcmp(cmd, "copyright") == 0)
330 else if (cmd[0] == 'd')
335 /* We don't do SQLID reduction on the pattern yet */
336 pattern = scan_option(&string, OT_NORMAL, NULL, true);
338 show_verbose = strchr(cmd, '+') ? true : false;
345 success = describeTableDetails(pattern, show_verbose);
347 /* standard listing of interesting things */
348 success = listTables("tvs", NULL, show_verbose);
351 success = describeAggregates(pattern, show_verbose);
354 success = objectDescription(pattern);
357 success = describeFunctions(pattern, show_verbose);
360 success = do_lo_list();
363 success = describeOperators(pattern);
366 success = permissionsList(pattern);
369 success = describeTypes(pattern, show_verbose);
376 success = listTables(&cmd[1], pattern, show_verbose);
379 success = describeUsers(pattern);
382 success = listDomains(pattern);
385 success = listConversions(pattern);
388 success = listCasts(pattern);
392 status = CMD_UNKNOWN;
401 * \e or \edit -- edit the current query buffer (or a file and make it
404 else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
410 psql_error("no query buffer\n");
415 fname = scan_option(&string, OT_NORMAL, NULL, true);
416 status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
421 /* \echo and \qecho */
422 else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
426 bool no_newline = false;
430 if (strcmp(cmd, "qecho") == 0)
431 fout = pset.queryFout;
435 while ((value = scan_option(&string, OT_NORMAL, "ed, false)))
437 if (!quoted && strcmp(value, "-n") == 0)
453 /* \encoding -- set/show client side encoding */
454 else if (strcmp(cmd, "encoding") == 0)
456 char *encoding = scan_option(&string, OT_NORMAL, NULL, false);
460 puts(pg_encoding_to_char(pset.encoding));
464 if (PQsetClientEncoding(pset.db, encoding) == -1)
465 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
469 /* save encoding info into psql internal data */
470 pset.encoding = PQclientEncoding(pset.db);
471 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
477 /* \f -- change field separator */
478 else if (strcmp(cmd, "f") == 0)
480 char *fname = scan_option(&string, OT_NORMAL, NULL, false);
482 success = do_pset("fieldsep", fname, &pset.popt, quiet);
486 /* \g means send query */
487 else if (strcmp(cmd, "g") == 0)
489 char *fname = scan_option(&string, OT_FILEPIPE, NULL, false);
494 pset.gfname = xstrdup(fname);
500 else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
502 helpSQL(options_string ? &options_string[strspn(options_string, " \t\n\r")] : NULL,
503 pset.popt.topt.pager);
504 /* set pointer to end of line */
506 string += strlen(string);
510 else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
512 if (pset.popt.topt.format != PRINT_HTML)
513 success = do_pset("format", "html", &pset.popt, quiet);
515 success = do_pset("format", "aligned", &pset.popt, quiet);
519 /* \i is include file */
520 else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
522 char *fname = scan_option(&string, OT_NORMAL, NULL, true);
526 psql_error("\\%s: missing required argument\n", cmd);
531 success = (process_file(fname) == EXIT_SUCCESS);
536 /* \l is list databases */
537 else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
538 success = listAllDbs(false);
539 else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
540 success = listAllDbs(true);
543 * large object things
545 else if (strncmp(cmd, "lo_", 3) == 0)
550 opt1 = scan_option(&string, OT_NORMAL, NULL, true);
551 opt2 = scan_option(&string, OT_NORMAL, NULL, true);
553 if (strcmp(cmd + 3, "export") == 0)
557 psql_error("\\%s: missing required argument\n", cmd);
561 success = do_lo_export(opt1, opt2);
564 else if (strcmp(cmd + 3, "import") == 0)
568 psql_error("\\%s: missing required argument\n", cmd);
572 success = do_lo_import(opt1, opt2);
575 else if (strcmp(cmd + 3, "list") == 0)
576 success = do_lo_list();
578 else if (strcmp(cmd + 3, "unlink") == 0)
582 psql_error("\\%s: missing required argument\n", cmd);
586 success = do_lo_unlink(opt1);
590 status = CMD_UNKNOWN;
597 /* \o -- set query output */
598 else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
600 char *fname = scan_option(&string, OT_FILEPIPE, NULL, true);
602 success = setQFout(fname);
606 /* \p prints the current query buffer */
607 else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
609 if (query_buf && query_buf->len > 0)
610 puts(query_buf->data);
612 puts(gettext("Query buffer is empty."));
616 /* \pset -- set printing parameters */
617 else if (strcmp(cmd, "pset") == 0)
619 char *opt0 = scan_option(&string, OT_NORMAL, NULL, false);
620 char *opt1 = scan_option(&string, OT_NORMAL, NULL, false);
624 psql_error("\\%s: missing required argument\n", cmd);
628 success = do_pset(opt0, opt1, &pset.popt, quiet);
635 else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
636 status = CMD_TERMINATE;
638 /* reset(clear) the buffer */
639 else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
641 resetPQExpBuffer(query_buf);
645 puts(gettext("Query buffer reset (cleared)."));
648 /* \s save history in a file or show it on the screen */
649 else if (strcmp(cmd, "s") == 0)
651 char *fname = scan_option(&string, OT_NORMAL, NULL, true);
653 success = saveHistory(fname ? fname : "/dev/tty");
655 if (success && !quiet && fname)
656 printf(gettext("Wrote history to %s.\n"), fname);
660 /* \set -- generalized set variable/option command */
661 else if (strcmp(cmd, "set") == 0)
663 char *opt0 = scan_option(&string, OT_NORMAL, NULL, false);
667 /* list all variables */
670 * XXX This is in utter violation of the GetVariable
671 * abstraction, but I have not bothered to do it better.
673 struct _variable *ptr;
675 for (ptr = pset.vars; ptr->next; ptr = ptr->next)
676 fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
682 * Set variable to the concatenation of the arguments.
687 opt = scan_option(&string, OT_NORMAL, NULL, false);
688 newval = xstrdup(opt ? opt : "");
691 while ((opt = scan_option(&string, OT_NORMAL, NULL, false)))
693 newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
696 psql_error("out of memory\n");
703 if (!SetVariable(pset.vars, opt0, newval))
705 psql_error("\\%s: error\n", cmd);
713 /* \t -- turn off headers and row count */
714 else if (strcmp(cmd, "t") == 0)
715 success = do_pset("tuples_only", NULL, &pset.popt, quiet);
718 /* \T -- define html <table ...> attributes */
719 else if (strcmp(cmd, "T") == 0)
721 char *value = scan_option(&string, OT_NORMAL, NULL, false);
723 success = do_pset("tableattr", value, &pset.popt, quiet);
727 /* \timing -- toggle timing of queries */
728 else if (strcmp(cmd, "timing") == 0)
730 pset.timing = !pset.timing;
734 puts(gettext(("Timing is on.")));
737 puts(gettext(("Timing is off.")));
744 else if (strcmp(cmd, "unset") == 0)
746 char *opt = scan_option(&string, OT_NORMAL, NULL, false);
750 psql_error("\\%s: missing required argument\n", cmd);
753 else if (!SetVariable(pset.vars, opt, NULL))
755 psql_error("\\%s: error\n", cmd);
761 /* \w -- write query buffer to file */
762 else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
765 bool is_pipe = false;
770 psql_error("no query buffer\n");
775 fname = scan_option(&string, OT_FILEPIPE, NULL, true);
779 psql_error("\\%s: missing required argument\n", cmd);
787 fd = popen(&fname[1], "w");
790 fd = fopen(fname, "w");
794 psql_error("%s: %s\n", fname, strerror(errno));
804 if (query_buf && query_buf->len > 0)
805 fprintf(fd, "%s\n", query_buf->data);
814 psql_error("%s: %s\n", fname, strerror(errno));
822 /* \x -- toggle expanded table representation */
823 else if (strcmp(cmd, "x") == 0)
824 success = do_pset("expanded", NULL, &pset.popt, quiet);
827 /* \z -- list table rights (equivalent to \dp) */
828 else if (strcmp(cmd, "z") == 0)
830 char *pattern = scan_option(&string, OT_NORMAL, NULL, true);
832 success = permissionsList(pattern);
837 /* \! -- shell escape */
838 else if (strcmp(cmd, "!") == 0)
840 success = do_shell(options_string);
841 /* wind pointer to end of line */
843 string += strlen(string);
846 /* \? -- slash command help */
847 else if (strcmp(cmd, "?") == 0)
848 slashUsage(pset.popt.topt.pager);
853 * These commands don't do anything. I just use them to test the
856 else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
861 fprintf(stderr, "+ optstr = |%s|\n", options_string);
862 while ((value = scan_option(&string, OT_NORMAL, NULL, true)))
864 fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
871 status = CMD_UNKNOWN;
876 /* eat the rest of the options string */
877 while ((val = scan_option(&string, OT_NORMAL, NULL, false)))
879 if (status != CMD_UNKNOWN)
880 psql_error("\\%s: extra argument '%s' ignored\n", cmd, val);
883 if (options_string && continue_parse)
884 *continue_parse = options_string + (string - string_cpy);
895 * *string points to possible option string on entry; on exit, it's updated
896 * to point past the option string (if any).
898 * type tells what processing, if any, to perform on the option string;
899 * for example, if it's a SQL identifier, we want to downcase any unquoted
902 * if quote is not NULL, *quote is set to 0 if no quoting was found, else
905 * if semicolon is true, trailing semicolon(s) that would otherwise be taken
906 * as part of the option string will be stripped.
908 * Return value is NULL if no option found, else a malloc'd copy of the
909 * processed option value.
912 scan_option(char **string, enum option_type type, char *quote, bool semicolon)
915 char *options_string;
921 if (!string || !(*string))
924 options_string = *string;
925 /* skip leading whitespace */
926 pos = strspn(options_string, " \t\n\r");
928 switch (options_string[pos])
931 * End of line: no option present
934 *string = &options_string[pos];
938 * Next command: treat like end of line
940 * XXX this means we can't conveniently accept options that start
941 * with a backslash; therefore, option processing that
942 * encourages use of backslashes is rather broken.
945 *string = &options_string[pos];
949 * A single quote has a psql internal meaning, such as for
950 * delimiting file names, and it also allows for such escape
956 unsigned short int bslash_count = 0;
958 for (jj = pos + 1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
960 if (options_string[jj] == '\'' && bslash_count % 2 == 0)
963 if (options_string[jj] == '\\')
969 if (options_string[jj] == 0)
971 psql_error("parse error at the end of line\n");
972 *string = &options_string[jj];
976 return_val = unescape(&options_string[pos + 1], jj - pos - 1);
977 *string = &options_string[jj + 1];
984 * Backticks are for command substitution, like in shells
991 PQExpBufferData output;
996 len = strcspn(options_string + pos + 1, "`");
997 if (options_string[pos + 1 + len] == 0)
999 psql_error("parse error at the end of line\n");
1000 *string = &options_string[pos + 1 + len];
1004 options_string[pos + 1 + len] = '\0';
1005 file = options_string + pos + 1;
1007 fd = popen(file, "r");
1010 psql_error("%s: %s\n", file, strerror(errno));
1014 initPQExpBuffer(&output);
1020 result = fread(buf, 1, 512, fd);
1023 psql_error("%s: %s\n", file, strerror(errno));
1027 appendBinaryPQExpBuffer(&output, buf, result);
1028 } while (!feof(fd));
1029 appendPQExpBufferChar(&output, '\0');
1032 if (fd && pclose(fd) == -1)
1034 psql_error("%s: %s\n", file, strerror(errno));
1040 if (output.data[strlen(output.data) - 1] == '\n')
1041 output.data[strlen(output.data) - 1] = '\0';
1042 return_val = output.data;
1046 return_val = xstrdup("");
1047 termPQExpBuffer(&output);
1050 options_string[pos + 1 + len] = '`';
1051 *string = options_string + pos + len + 2;
1058 * Variable substitution
1066 token_end = strcspn(&options_string[pos + 1], " \t\n\r");
1067 save_char = options_string[pos + token_end + 1];
1068 options_string[pos + token_end + 1] = '\0';
1069 value = GetVariable(pset.vars, options_string + pos + 1);
1072 return_val = xstrdup(value);
1073 options_string[pos + token_end + 1] = save_char;
1074 *string = &options_string[pos + token_end + 1];
1075 /* XXX should we set *quote to ':' here? */
1080 * | could be the beginning of a pipe if so, take rest of line
1084 if (type == OT_FILEPIPE)
1086 *string += strlen(*string);
1087 return xstrdup(options_string + pos);
1089 /* fallthrough for other option types */
1092 * Default case: token extends to next whitespace, except that
1093 * whitespace within double quotes doesn't end the token.
1095 * If we are processing the option as a SQL identifier, then
1096 * downcase unquoted letters and remove double-quotes --- but
1097 * doubled double-quotes become output double-quotes, per
1100 * Note that a string like FOO"BAR"BAZ will be converted to
1101 * fooBARbaz; this is somewhat inconsistent with the SQL spec,
1102 * which would have us parse it as several identifiers. But
1103 * for psql's purposes, we want a string like "foo"."bar" to
1104 * be treated as one option, so there's little choice.
1108 bool inquotes = false;
1112 /* Find end of option */
1114 cp = &options_string[pos];
1117 /* Find next quote, whitespace, or end of string */
1118 cp += strcspn(cp, "\" \t\n\r");
1123 psql_error("parse error at the end of line\n");
1134 break; /* whitespace or end of string */
1144 /* Copy the option */
1145 token_len = cp - &options_string[pos];
1147 return_val = malloc(token_len + 1);
1150 psql_error("out of memory\n");
1154 memcpy(return_val, &options_string[pos], token_len);
1155 return_val[token_len] = '\0';
1157 /* Strip any trailing semi-colons if requested */
1162 for (i = token_len - 1;
1163 i >= 0 && return_val[i] == ';';
1169 /* nothing left after stripping the semicolon... */
1174 if (i < (int) token_len - 1)
1175 return_val[i + 1] = '\0';
1179 * If SQL identifier processing was requested, then we
1180 * strip out excess double quotes and downcase unquoted
1183 if (type == OT_SQLID || type == OT_SQLIDHACK)
1192 if (inquotes && cp[1] == '"')
1194 /* Keep the first quote, remove the second */
1197 inquotes = !inquotes;
1198 /* Collapse out quote at *cp */
1199 memmove(cp, cp + 1, strlen(cp));
1200 /* do not advance cp */
1204 if (!inquotes && type == OT_SQLID)
1206 if (isupper((unsigned char) *cp))
1207 *cp = tolower((unsigned char) *cp);
1209 cp += PQmblen(cp, pset.encoding);
1224 * Replaces \n, \t, and the like.
1226 * The return value is malloc()'ed.
1229 unescape(const unsigned char *source, size_t len)
1231 const unsigned char *p;
1232 bool esc = false; /* Last character we saw was the escape
1238 #ifdef USE_ASSERT_CHECKING
1242 length = Min(len, strlen(source)) + 1;
1244 tmp = destination = malloc(length);
1247 psql_error("out of memory\n");
1251 for (p = source; p - source < (int) len && *p; p += PQmblen(p, pset.encoding))
1288 l = strtol(p, &end, 0);
1300 else if (*p == '\\')
1306 const unsigned char *mp = p;
1308 for (i = 0; i < PQmblen(p, pset.encoding); i++)
1321 * -- handler for \connect
1323 * Connects to a database (new_dbname) as a certain user (new_user).
1324 * The new user can be NULL. A db name of "-" is the same as the old one.
1325 * (That is, the one currently in pset. But pset.db can also be NULL. A NULL
1326 * dbname is handled by libpq.)
1327 * Returns true if all ok, false if the new connection couldn't be established.
1328 * The old connection will be kept if the session is interactive.
1331 do_connect(const char *new_dbname, const char *new_user)
1333 PGconn *oldconn = pset.db;
1334 const char *dbparam = NULL;
1335 const char *userparam = NULL;
1336 const char *pwparam = NULL;
1337 char *prompted_password = NULL;
1339 bool success = false;
1341 /* Delete variables (in case we fail before setting them anew) */
1342 SetVariable(pset.vars, "DBNAME", NULL);
1343 SetVariable(pset.vars, "USER", NULL);
1344 SetVariable(pset.vars, "HOST", NULL);
1345 SetVariable(pset.vars, "PORT", NULL);
1346 SetVariable(pset.vars, "ENCODING", NULL);
1348 /* If dbname is "" then use old name, else new one (even if NULL) */
1349 if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
1350 dbparam = PQdb(oldconn);
1352 dbparam = new_dbname;
1354 /* If user is "" then use the old one */
1355 if (new_user && PQuser(oldconn) && strcmp(new_user, "") == 0)
1356 userparam = PQuser(oldconn);
1358 userparam = new_user;
1360 /* need to prompt for password? */
1361 if (pset.getPassword)
1362 pwparam = prompted_password = simple_prompt("Password: ", 100, false);
1365 * Use old password (if any) if no new one given and we are
1366 * reconnecting as same user
1368 if (!pwparam && oldconn && PQuser(oldconn) && userparam &&
1369 strcmp(PQuser(oldconn), userparam) == 0)
1370 pwparam = PQpass(oldconn);
1375 pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
1376 NULL, NULL, dbparam, userparam, pwparam);
1378 if (PQstatus(pset.db) == CONNECTION_BAD &&
1379 strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0 &&
1384 free(prompted_password);
1385 prompted_password = NULL;
1386 pwparam = prompted_password = simple_prompt("Password: ", 100, false);
1388 } while (need_pass);
1390 free(prompted_password);
1393 * If connection failed, try at least keep the old one. That's
1394 * probably more convenient than just kicking you out of the program.
1396 if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD)
1398 if (pset.cur_cmd_interactive)
1400 psql_error("%s", PQerrorMessage(pset.db));
1404 fputs(gettext("Previous connection kept\n"), stderr);
1413 * we don't want unpredictable things to happen in scripting
1416 psql_error("\\connect: %s", PQerrorMessage(pset.db));
1427 if (userparam != new_user) /* no new user */
1428 printf(gettext("You are now connected to database %s.\n"), dbparam);
1429 else if (dbparam != new_dbname) /* no new db */
1430 printf(gettext("You are now connected as new user %s.\n"), new_user);
1433 printf(gettext("You are now connected to database %s as user %s.\n"),
1434 PQdb(pset.db), PQuser(pset.db));
1443 PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
1444 pset.encoding = PQclientEncoding(pset.db);
1446 /* Update variables */
1447 SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
1448 SetVariable(pset.vars, "USER", PQuser(pset.db));
1449 SetVariable(pset.vars, "HOST", PQhost(pset.db));
1450 SetVariable(pset.vars, "PORT", PQport(pset.db));
1451 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
1453 pset.issuper = test_superuser(PQuser(pset.db));
1461 * Test if the given user is a database superuser.
1462 * (Is used to set up the prompt right.)
1465 test_superuser(const char *username)
1468 PQExpBufferData buf;
1475 * Use begin/commit to avoid starting a transaction block if server
1476 * has autocommit off by default.
1478 initPQExpBuffer(&buf);
1479 printfPQExpBuffer(&buf, "BEGIN; SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'; COMMIT", username);
1480 res = PSQLexec(buf.data, true);
1481 termPQExpBuffer(&buf);
1484 (res && PQntuples(res) > 0 && PQnfields(res) > 0
1485 && !PQgetisnull(res, 0, 0)
1486 && PQgetvalue(res, 0, 0)
1487 && strcmp(PQgetvalue(res, 0, 0), "t") == 0);
1495 * do_edit -- handler for \e
1497 * If you do not specify a filename, the current query buffer will be copied
1498 * into a temporary one.
1502 editFile(const char *fname)
1504 const char *editorName;
1508 #ifdef USE_ASSERT_CHECKING
1515 /* Find an editor to use */
1516 editorName = getenv("PSQL_EDITOR");
1518 editorName = getenv("EDITOR");
1520 editorName = getenv("VISUAL");
1522 editorName = DEFAULT_EDITOR;
1524 sys = malloc(strlen(editorName) + strlen(fname) + 10 + 1);
1527 sprintf(sys, "exec '%s' '%s'", editorName, fname);
1528 result = system(sys);
1530 psql_error("could not start editor %s\n", editorName);
1531 else if (result == 127)
1532 psql_error("could not start /bin/sh\n");
1541 do_edit(const char *filename_arg, PQExpBuffer query_buf)
1543 char fnametmp[MAXPGPATH];
1544 FILE *stream = NULL;
1555 fname = filename_arg;
1559 /* make a temp file to edit */
1561 const char *tmpdirenv = getenv("TMPDIR");
1563 snprintf(fnametmp, sizeof(fnametmp), "%s/psql.edit.%ld.%ld",
1564 tmpdirenv ? tmpdirenv : "/tmp",
1565 (long) geteuid(), (long) getpid());
1567 GetTempFileName(".", "psql", 0, fnametmp);
1569 fname = (const char *) fnametmp;
1571 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
1573 stream = fdopen(fd, "w");
1575 if (fd == -1 || !stream)
1577 psql_error("could not open temporary file %s: %s\n", fname, strerror(errno));
1582 unsigned int ql = query_buf->len;
1584 if (ql == 0 || query_buf->data[ql - 1] != '\n')
1586 appendPQExpBufferChar(query_buf, '\n');
1590 if (fwrite(query_buf->data, 1, ql, stream) != ql)
1592 psql_error("%s: %s\n", fname, strerror(errno));
1603 if (!error && stat(fname, &before) != 0)
1605 psql_error("%s: %s\n", fname, strerror(errno));
1612 error = !editFile(fname);
1615 if (!error && stat(fname, &after) != 0)
1617 psql_error("%s: %s\n", fname, strerror(errno));
1621 if (!error && before.st_mtime != after.st_mtime)
1627 stream = fopen(fname, "r");
1630 psql_error("%s: %s\n", fname, strerror(errno));
1635 /* read file back in */
1638 resetPQExpBuffer(query_buf);
1639 while (fgets(line, sizeof(line), stream) != NULL)
1640 appendPQExpBufferStr(query_buf, line);
1644 psql_error("%s: %s\n", fname, strerror(errno));
1653 /* remove temp file */
1656 if (remove(fname) == -1)
1658 psql_error("%s: %s\n", fname, strerror(errno));
1671 * Read commands from filename and then them to the main processing loop
1672 * Handler for \i, but can be used for other things as well.
1675 process_file(char *filename)
1684 fd = fopen(filename, "r");
1688 psql_error("%s: %s\n", filename, strerror(errno));
1692 oldfilename = pset.inputfile;
1693 pset.inputfile = filename;
1694 result = MainLoop(fd);
1696 pset.inputfile = oldfilename;
1707 _align2string(enum printFormat in)
1714 case PRINT_UNALIGNED:
1732 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
1736 #ifdef USE_ASSERT_CHECKING
1744 vallen = strlen(value);
1747 if (strcmp(param, "format") == 0)
1751 else if (strncasecmp("unaligned", value, vallen) == 0)
1752 popt->topt.format = PRINT_UNALIGNED;
1753 else if (strncasecmp("aligned", value, vallen) == 0)
1754 popt->topt.format = PRINT_ALIGNED;
1755 else if (strncasecmp("html", value, vallen) == 0)
1756 popt->topt.format = PRINT_HTML;
1757 else if (strncasecmp("latex", value, vallen) == 0)
1758 popt->topt.format = PRINT_LATEX;
1761 psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n");
1766 printf(gettext("Output format is %s.\n"), _align2string(popt->topt.format));
1769 /* set border style/width */
1770 else if (strcmp(param, "border") == 0)
1773 popt->topt.border = atoi(value);
1776 printf(gettext("Border style is %d.\n"), popt->topt.border);
1779 /* set expanded/vertical mode */
1780 else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
1782 popt->topt.expanded = !popt->topt.expanded;
1784 printf(popt->topt.expanded
1785 ? gettext("Expanded display is on.\n")
1786 : gettext("Expanded display is off.\n"));
1790 else if (strcmp(param, "null") == 0)
1794 free(popt->nullPrint);
1795 popt->nullPrint = xstrdup(value);
1798 printf(gettext("Null display is '%s'.\n"), popt->nullPrint ? popt->nullPrint : "");
1801 /* field separator for unaligned text */
1802 else if (strcmp(param, "fieldsep") == 0)
1806 free(popt->topt.fieldSep);
1807 popt->topt.fieldSep = xstrdup(value);
1810 printf(gettext("Field separator is '%s'.\n"), popt->topt.fieldSep);
1813 /* record separator for unaligned text */
1814 else if (strcmp(param, "recordsep") == 0)
1818 free(popt->topt.recordSep);
1819 popt->topt.recordSep = xstrdup(value);
1823 if (strcmp(popt->topt.recordSep, "\n") == 0)
1824 printf(gettext("Record separator is <newline>."));
1826 printf(gettext("Record separator is '%s'.\n"), popt->topt.recordSep);
1830 /* toggle between full and barebones format */
1831 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
1833 popt->topt.tuples_only = !popt->topt.tuples_only;
1836 if (popt->topt.tuples_only)
1837 puts(gettext("Showing only tuples."));
1839 puts(gettext("Tuples only is off."));
1843 /* set title override */
1844 else if (strcmp(param, "title") == 0)
1850 popt->title = xstrdup(value);
1855 printf(gettext("Title is \"%s\".\n"), popt->title);
1857 printf(gettext("Title is unset.\n"));
1861 /* set HTML table tag options */
1862 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
1864 free(popt->topt.tableAttr);
1866 popt->topt.tableAttr = NULL;
1868 popt->topt.tableAttr = xstrdup(value);
1872 if (popt->topt.tableAttr)
1873 printf(gettext("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
1875 printf(gettext("Table attributes unset.\n"));
1879 /* toggle use of pager */
1880 else if (strcmp(param, "pager") == 0)
1882 if (value && strcasecmp(value, "always") == 0)
1883 popt->topt.pager = 2;
1884 else if (popt->topt.pager == 1)
1885 popt->topt.pager = 0;
1887 popt->topt.pager = 1;
1890 if (popt->topt.pager == 1)
1891 puts(gettext("Using pager is on."));
1892 else if (popt->topt.pager == 2)
1893 puts(gettext("Using pager is always."));
1895 puts(gettext("Using pager is off."));
1899 /* disable "(x rows)" footer */
1900 else if (strcmp(param, "footer") == 0)
1902 popt->default_footer = !popt->default_footer;
1905 if (popt->default_footer)
1906 puts(gettext("Default footer is on."));
1908 puts(gettext("Default footer is off."));
1914 psql_error("\\pset: unknown option: %s\n", param);
1923 #define DEFAULT_SHELL "/bin/sh"
1926 do_shell(const char *command)
1933 const char *shellName;
1935 shellName = getenv("SHELL");
1936 if (shellName == NULL)
1937 shellName = DEFAULT_SHELL;
1939 sys = malloc(strlen(shellName) + 16);
1942 psql_error("out of memory\n");
1943 if (pset.cur_cmd_interactive)
1948 sprintf(sys, "exec %s", shellName);
1949 result = system(sys);
1953 result = system(command);
1955 if (result == 127 || result == -1)
1957 psql_error("\\!: failed\n");