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.89 2003/02/13 04:08:16 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 = listConversions(pattern);
357 success = listCasts(pattern);
360 success = objectDescription(pattern);
363 success = listDomains(pattern);
366 success = describeFunctions(pattern, show_verbose);
369 success = do_lo_list();
372 success = listSchemas(pattern);
375 success = describeOperators(pattern);
378 success = permissionsList(pattern);
381 success = describeTypes(pattern, show_verbose);
388 success = listTables(&cmd[1], pattern, show_verbose);
391 success = describeUsers(pattern);
395 status = CMD_UNKNOWN;
404 * \e or \edit -- edit the current query buffer (or a file and make it
407 else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
413 psql_error("no query buffer\n");
418 fname = scan_option(&string, OT_NORMAL, NULL, true);
419 status = do_edit(fname, query_buf) ? CMD_NEWEDIT : CMD_ERROR;
424 /* \echo and \qecho */
425 else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
429 bool no_newline = false;
433 if (strcmp(cmd, "qecho") == 0)
434 fout = pset.queryFout;
438 while ((value = scan_option(&string, OT_NORMAL, "ed, false)))
440 if (!quoted && strcmp(value, "-n") == 0)
456 /* \encoding -- set/show client side encoding */
457 else if (strcmp(cmd, "encoding") == 0)
459 char *encoding = scan_option(&string, OT_NORMAL, NULL, false);
463 puts(pg_encoding_to_char(pset.encoding));
467 if (PQsetClientEncoding(pset.db, encoding) == -1)
468 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
472 /* save encoding info into psql internal data */
473 pset.encoding = PQclientEncoding(pset.db);
474 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
480 /* \f -- change field separator */
481 else if (strcmp(cmd, "f") == 0)
483 char *fname = scan_option(&string, OT_NORMAL, NULL, false);
485 success = do_pset("fieldsep", fname, &pset.popt, quiet);
489 /* \g means send query */
490 else if (strcmp(cmd, "g") == 0)
492 char *fname = scan_option(&string, OT_FILEPIPE, NULL, false);
497 pset.gfname = xstrdup(fname);
503 else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
505 helpSQL(options_string ? &options_string[strspn(options_string, " \t\n\r")] : NULL,
506 pset.popt.topt.pager);
507 /* set pointer to end of line */
509 string += strlen(string);
513 else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
515 if (pset.popt.topt.format != PRINT_HTML)
516 success = do_pset("format", "html", &pset.popt, quiet);
518 success = do_pset("format", "aligned", &pset.popt, quiet);
522 /* \i is include file */
523 else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
525 char *fname = scan_option(&string, OT_NORMAL, NULL, true);
529 psql_error("\\%s: missing required argument\n", cmd);
534 success = (process_file(fname) == EXIT_SUCCESS);
539 /* \l is list databases */
540 else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
541 success = listAllDbs(false);
542 else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
543 success = listAllDbs(true);
546 * large object things
548 else if (strncmp(cmd, "lo_", 3) == 0)
553 opt1 = scan_option(&string, OT_NORMAL, NULL, true);
554 opt2 = scan_option(&string, OT_NORMAL, NULL, true);
556 if (strcmp(cmd + 3, "export") == 0)
560 psql_error("\\%s: missing required argument\n", cmd);
564 success = do_lo_export(opt1, opt2);
567 else if (strcmp(cmd + 3, "import") == 0)
571 psql_error("\\%s: missing required argument\n", cmd);
575 success = do_lo_import(opt1, opt2);
578 else if (strcmp(cmd + 3, "list") == 0)
579 success = do_lo_list();
581 else if (strcmp(cmd + 3, "unlink") == 0)
585 psql_error("\\%s: missing required argument\n", cmd);
589 success = do_lo_unlink(opt1);
593 status = CMD_UNKNOWN;
600 /* \o -- set query output */
601 else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
603 char *fname = scan_option(&string, OT_FILEPIPE, NULL, true);
605 success = setQFout(fname);
609 /* \p prints the current query buffer */
610 else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
612 if (query_buf && query_buf->len > 0)
613 puts(query_buf->data);
615 puts(gettext("Query buffer is empty."));
619 /* \pset -- set printing parameters */
620 else if (strcmp(cmd, "pset") == 0)
622 char *opt0 = scan_option(&string, OT_NORMAL, NULL, false);
623 char *opt1 = scan_option(&string, OT_NORMAL, NULL, false);
627 psql_error("\\%s: missing required argument\n", cmd);
631 success = do_pset(opt0, opt1, &pset.popt, quiet);
638 else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
639 status = CMD_TERMINATE;
641 /* reset(clear) the buffer */
642 else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
644 resetPQExpBuffer(query_buf);
648 puts(gettext("Query buffer reset (cleared)."));
651 /* \s save history in a file or show it on the screen */
652 else if (strcmp(cmd, "s") == 0)
654 char *fname = scan_option(&string, OT_NORMAL, NULL, true);
656 success = saveHistory(fname ? fname : "/dev/tty");
658 if (success && !quiet && fname)
659 printf(gettext("Wrote history to %s.\n"), fname);
663 /* \set -- generalized set variable/option command */
664 else if (strcmp(cmd, "set") == 0)
666 char *opt0 = scan_option(&string, OT_NORMAL, NULL, false);
670 /* list all variables */
673 * XXX This is in utter violation of the GetVariable
674 * abstraction, but I have not bothered to do it better.
676 struct _variable *ptr;
678 for (ptr = pset.vars; ptr->next; ptr = ptr->next)
679 fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
685 * Set variable to the concatenation of the arguments.
690 opt = scan_option(&string, OT_NORMAL, NULL, false);
691 newval = xstrdup(opt ? opt : "");
694 while ((opt = scan_option(&string, OT_NORMAL, NULL, false)))
696 newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
699 psql_error("out of memory\n");
706 if (!SetVariable(pset.vars, opt0, newval))
708 psql_error("\\%s: error\n", cmd);
716 /* \t -- turn off headers and row count */
717 else if (strcmp(cmd, "t") == 0)
718 success = do_pset("tuples_only", NULL, &pset.popt, quiet);
721 /* \T -- define html <table ...> attributes */
722 else if (strcmp(cmd, "T") == 0)
724 char *value = scan_option(&string, OT_NORMAL, NULL, false);
726 success = do_pset("tableattr", value, &pset.popt, quiet);
730 /* \timing -- toggle timing of queries */
731 else if (strcmp(cmd, "timing") == 0)
733 pset.timing = !pset.timing;
737 puts(gettext(("Timing is on.")));
740 puts(gettext(("Timing is off.")));
747 else if (strcmp(cmd, "unset") == 0)
749 char *opt = scan_option(&string, OT_NORMAL, NULL, false);
753 psql_error("\\%s: missing required argument\n", cmd);
756 else if (!SetVariable(pset.vars, opt, NULL))
758 psql_error("\\%s: error\n", cmd);
764 /* \w -- write query buffer to file */
765 else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
768 bool is_pipe = false;
773 psql_error("no query buffer\n");
778 fname = scan_option(&string, OT_FILEPIPE, NULL, true);
782 psql_error("\\%s: missing required argument\n", cmd);
790 fd = popen(&fname[1], "w");
793 fd = fopen(fname, "w");
797 psql_error("%s: %s\n", fname, strerror(errno));
807 if (query_buf && query_buf->len > 0)
808 fprintf(fd, "%s\n", query_buf->data);
817 psql_error("%s: %s\n", fname, strerror(errno));
825 /* \x -- toggle expanded table representation */
826 else if (strcmp(cmd, "x") == 0)
827 success = do_pset("expanded", NULL, &pset.popt, quiet);
830 /* \z -- list table rights (equivalent to \dp) */
831 else if (strcmp(cmd, "z") == 0)
833 char *pattern = scan_option(&string, OT_NORMAL, NULL, true);
835 success = permissionsList(pattern);
840 /* \! -- shell escape */
841 else if (strcmp(cmd, "!") == 0)
843 success = do_shell(options_string);
844 /* wind pointer to end of line */
846 string += strlen(string);
849 /* \? -- slash command help */
850 else if (strcmp(cmd, "?") == 0)
851 slashUsage(pset.popt.topt.pager);
856 * These commands don't do anything. I just use them to test the
859 else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
864 fprintf(stderr, "+ optstr = |%s|\n", options_string);
865 while ((value = scan_option(&string, OT_NORMAL, NULL, true)))
867 fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
874 status = CMD_UNKNOWN;
879 /* eat the rest of the options string */
880 while ((val = scan_option(&string, OT_NORMAL, NULL, false)))
882 if (status != CMD_UNKNOWN)
883 psql_error("\\%s: extra argument '%s' ignored\n", cmd, val);
886 if (options_string && continue_parse)
887 *continue_parse = options_string + (string - string_cpy);
898 * *string points to possible option string on entry; on exit, it's updated
899 * to point past the option string (if any).
901 * type tells what processing, if any, to perform on the option string;
902 * for example, if it's a SQL identifier, we want to downcase any unquoted
905 * if quote is not NULL, *quote is set to 0 if no quoting was found, else
908 * if semicolon is true, trailing semicolon(s) that would otherwise be taken
909 * as part of the option string will be stripped.
911 * Return value is NULL if no option found, else a malloc'd copy of the
912 * processed option value.
915 scan_option(char **string, enum option_type type, char *quote, bool semicolon)
918 char *options_string;
924 if (!string || !(*string))
927 options_string = *string;
928 /* skip leading whitespace */
929 pos = strspn(options_string, " \t\n\r");
931 switch (options_string[pos])
934 * End of line: no option present
937 *string = &options_string[pos];
941 * Next command: treat like end of line
943 * XXX this means we can't conveniently accept options that start
944 * with a backslash; therefore, option processing that
945 * encourages use of backslashes is rather broken.
948 *string = &options_string[pos];
952 * A single quote has a psql internal meaning, such as for
953 * delimiting file names, and it also allows for such escape
959 unsigned short int bslash_count = 0;
961 for (jj = pos + 1; options_string[jj]; jj += PQmblen(&options_string[jj], pset.encoding))
963 if (options_string[jj] == '\'' && bslash_count % 2 == 0)
966 if (options_string[jj] == '\\')
972 if (options_string[jj] == 0)
974 psql_error("parse error at the end of line\n");
975 *string = &options_string[jj];
979 return_val = unescape(&options_string[pos + 1], jj - pos - 1);
980 *string = &options_string[jj + 1];
987 * Backticks are for command substitution, like in shells
994 PQExpBufferData output;
999 len = strcspn(options_string + pos + 1, "`");
1000 if (options_string[pos + 1 + len] == 0)
1002 psql_error("parse error at the end of line\n");
1003 *string = &options_string[pos + 1 + len];
1007 options_string[pos + 1 + len] = '\0';
1008 file = options_string + pos + 1;
1010 fd = popen(file, "r");
1013 psql_error("%s: %s\n", file, strerror(errno));
1017 initPQExpBuffer(&output);
1023 result = fread(buf, 1, 512, fd);
1026 psql_error("%s: %s\n", file, strerror(errno));
1030 appendBinaryPQExpBuffer(&output, buf, result);
1031 } while (!feof(fd));
1032 appendPQExpBufferChar(&output, '\0');
1035 if (fd && pclose(fd) == -1)
1037 psql_error("%s: %s\n", file, strerror(errno));
1043 if (output.data[strlen(output.data) - 1] == '\n')
1044 output.data[strlen(output.data) - 1] = '\0';
1045 return_val = output.data;
1049 return_val = xstrdup("");
1050 termPQExpBuffer(&output);
1053 options_string[pos + 1 + len] = '`';
1054 *string = options_string + pos + len + 2;
1061 * Variable substitution
1069 token_end = strcspn(&options_string[pos + 1], " \t\n\r");
1070 save_char = options_string[pos + token_end + 1];
1071 options_string[pos + token_end + 1] = '\0';
1072 value = GetVariable(pset.vars, options_string + pos + 1);
1075 return_val = xstrdup(value);
1076 options_string[pos + token_end + 1] = save_char;
1077 *string = &options_string[pos + token_end + 1];
1078 /* XXX should we set *quote to ':' here? */
1083 * | could be the beginning of a pipe if so, take rest of line
1087 if (type == OT_FILEPIPE)
1089 *string += strlen(*string);
1090 return xstrdup(options_string + pos);
1092 /* fallthrough for other option types */
1095 * Default case: token extends to next whitespace, except that
1096 * whitespace within double quotes doesn't end the token.
1098 * If we are processing the option as a SQL identifier, then
1099 * downcase unquoted letters and remove double-quotes --- but
1100 * doubled double-quotes become output double-quotes, per
1103 * Note that a string like FOO"BAR"BAZ will be converted to
1104 * fooBARbaz; this is somewhat inconsistent with the SQL spec,
1105 * which would have us parse it as several identifiers. But
1106 * for psql's purposes, we want a string like "foo"."bar" to
1107 * be treated as one option, so there's little choice.
1111 bool inquotes = false;
1115 /* Find end of option */
1117 cp = &options_string[pos];
1120 /* Find next quote, whitespace, or end of string */
1121 cp += strcspn(cp, "\" \t\n\r");
1126 psql_error("parse error at the end of line\n");
1137 break; /* whitespace or end of string */
1147 /* Copy the option */
1148 token_len = cp - &options_string[pos];
1150 return_val = malloc(token_len + 1);
1153 psql_error("out of memory\n");
1157 memcpy(return_val, &options_string[pos], token_len);
1158 return_val[token_len] = '\0';
1160 /* Strip any trailing semi-colons if requested */
1165 for (i = token_len - 1;
1166 i >= 0 && return_val[i] == ';';
1172 /* nothing left after stripping the semicolon... */
1177 if (i < (int) token_len - 1)
1178 return_val[i + 1] = '\0';
1182 * If SQL identifier processing was requested, then we
1183 * strip out excess double quotes and downcase unquoted
1186 if (type == OT_SQLID || type == OT_SQLIDHACK)
1195 if (inquotes && cp[1] == '"')
1197 /* Keep the first quote, remove the second */
1200 inquotes = !inquotes;
1201 /* Collapse out quote at *cp */
1202 memmove(cp, cp + 1, strlen(cp));
1203 /* do not advance cp */
1207 if (!inquotes && type == OT_SQLID)
1209 if (isupper((unsigned char) *cp))
1210 *cp = tolower((unsigned char) *cp);
1212 cp += PQmblen(cp, pset.encoding);
1227 * Replaces \n, \t, and the like.
1229 * The return value is malloc()'ed.
1232 unescape(const unsigned char *source, size_t len)
1234 const unsigned char *p;
1235 bool esc = false; /* Last character we saw was the escape
1241 #ifdef USE_ASSERT_CHECKING
1245 length = Min(len, strlen(source)) + 1;
1247 tmp = destination = malloc(length);
1250 psql_error("out of memory\n");
1254 for (p = source; p - source < (int) len && *p; p += PQmblen(p, pset.encoding))
1291 l = strtol(p, &end, 0);
1303 else if (*p == '\\')
1309 const unsigned char *mp = p;
1311 for (i = 0; i < PQmblen(p, pset.encoding); i++)
1324 * -- handler for \connect
1326 * Connects to a database (new_dbname) as a certain user (new_user).
1327 * The new user can be NULL. A db name of "-" is the same as the old one.
1328 * (That is, the one currently in pset. But pset.db can also be NULL. A NULL
1329 * dbname is handled by libpq.)
1330 * Returns true if all ok, false if the new connection couldn't be established.
1331 * The old connection will be kept if the session is interactive.
1334 do_connect(const char *new_dbname, const char *new_user)
1336 PGconn *oldconn = pset.db;
1337 const char *dbparam = NULL;
1338 const char *userparam = NULL;
1339 const char *pwparam = NULL;
1340 char *prompted_password = NULL;
1342 bool success = false;
1344 /* Delete variables (in case we fail before setting them anew) */
1345 SetVariable(pset.vars, "DBNAME", NULL);
1346 SetVariable(pset.vars, "USER", NULL);
1347 SetVariable(pset.vars, "HOST", NULL);
1348 SetVariable(pset.vars, "PORT", NULL);
1349 SetVariable(pset.vars, "ENCODING", NULL);
1351 /* If dbname is "" then use old name, else new one (even if NULL) */
1352 if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
1353 dbparam = PQdb(oldconn);
1355 dbparam = new_dbname;
1357 /* If user is "" then use the old one */
1358 if (new_user && PQuser(oldconn) && strcmp(new_user, "") == 0)
1359 userparam = PQuser(oldconn);
1361 userparam = new_user;
1363 /* need to prompt for password? */
1364 if (pset.getPassword)
1365 pwparam = prompted_password = simple_prompt("Password: ", 100, false);
1368 * Use old password (if any) if no new one given and we are
1369 * reconnecting as same user
1371 if (!pwparam && oldconn && PQuser(oldconn) && userparam &&
1372 strcmp(PQuser(oldconn), userparam) == 0)
1373 pwparam = PQpass(oldconn);
1378 pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
1379 NULL, NULL, dbparam, userparam, pwparam);
1381 if (PQstatus(pset.db) == CONNECTION_BAD &&
1382 strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0 &&
1387 free(prompted_password);
1388 prompted_password = NULL;
1389 pwparam = prompted_password = simple_prompt("Password: ", 100, false);
1391 } while (need_pass);
1393 free(prompted_password);
1396 * If connection failed, try at least keep the old one. That's
1397 * probably more convenient than just kicking you out of the program.
1399 if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD)
1401 if (pset.cur_cmd_interactive)
1403 psql_error("%s", PQerrorMessage(pset.db));
1407 fputs(gettext("Previous connection kept\n"), stderr);
1416 * we don't want unpredictable things to happen in scripting
1419 psql_error("\\connect: %s", PQerrorMessage(pset.db));
1430 if (userparam != new_user) /* no new user */
1431 printf(gettext("You are now connected to database %s.\n"), dbparam);
1432 else if (dbparam != new_dbname) /* no new db */
1433 printf(gettext("You are now connected as new user %s.\n"), new_user);
1436 printf(gettext("You are now connected to database %s as user %s.\n"),
1437 PQdb(pset.db), PQuser(pset.db));
1446 PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
1447 pset.encoding = PQclientEncoding(pset.db);
1449 /* Update variables */
1450 SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
1451 SetVariable(pset.vars, "USER", PQuser(pset.db));
1452 SetVariable(pset.vars, "HOST", PQhost(pset.db));
1453 SetVariable(pset.vars, "PORT", PQport(pset.db));
1454 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
1456 pset.issuper = test_superuser(PQuser(pset.db));
1464 * Test if the given user is a database superuser.
1465 * (Is used to set up the prompt right.)
1468 test_superuser(const char *username)
1471 PQExpBufferData buf;
1478 * Use begin/commit to avoid starting a transaction block if server
1479 * has autocommit off by default.
1481 initPQExpBuffer(&buf);
1482 printfPQExpBuffer(&buf, "BEGIN; SELECT usesuper FROM pg_catalog.pg_user WHERE usename = '%s'; COMMIT", username);
1483 res = PSQLexec(buf.data, true);
1484 termPQExpBuffer(&buf);
1487 (res && PQntuples(res) > 0 && PQnfields(res) > 0
1488 && !PQgetisnull(res, 0, 0)
1489 && PQgetvalue(res, 0, 0)
1490 && strcmp(PQgetvalue(res, 0, 0), "t") == 0);
1498 * do_edit -- handler for \e
1500 * If you do not specify a filename, the current query buffer will be copied
1501 * into a temporary one.
1505 editFile(const char *fname)
1507 const char *editorName;
1511 #ifdef USE_ASSERT_CHECKING
1518 /* Find an editor to use */
1519 editorName = getenv("PSQL_EDITOR");
1521 editorName = getenv("EDITOR");
1523 editorName = getenv("VISUAL");
1525 editorName = DEFAULT_EDITOR;
1527 sys = malloc(strlen(editorName) + strlen(fname) + 10 + 1);
1530 sprintf(sys, "exec %s '%s'", editorName, fname);
1531 result = system(sys);
1533 psql_error("could not start editor %s\n", editorName);
1534 else if (result == 127)
1535 psql_error("could not start /bin/sh\n");
1544 do_edit(const char *filename_arg, PQExpBuffer query_buf)
1546 char fnametmp[MAXPGPATH];
1547 FILE *stream = NULL;
1558 fname = filename_arg;
1562 /* make a temp file to edit */
1564 const char *tmpdirenv = getenv("TMPDIR");
1566 snprintf(fnametmp, sizeof(fnametmp), "%s/psql.edit.%ld.%ld",
1567 tmpdirenv ? tmpdirenv : "/tmp",
1568 (long) geteuid(), (long) getpid());
1570 GetTempFileName(".", "psql", 0, fnametmp);
1572 fname = (const char *) fnametmp;
1574 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
1576 stream = fdopen(fd, "w");
1578 if (fd == -1 || !stream)
1580 psql_error("could not open temporary file %s: %s\n", fname, strerror(errno));
1585 unsigned int ql = query_buf->len;
1587 if (ql == 0 || query_buf->data[ql - 1] != '\n')
1589 appendPQExpBufferChar(query_buf, '\n');
1593 if (fwrite(query_buf->data, 1, ql, stream) != ql)
1595 psql_error("%s: %s\n", fname, strerror(errno));
1606 if (!error && stat(fname, &before) != 0)
1608 psql_error("%s: %s\n", fname, strerror(errno));
1615 error = !editFile(fname);
1618 if (!error && stat(fname, &after) != 0)
1620 psql_error("%s: %s\n", fname, strerror(errno));
1624 if (!error && before.st_mtime != after.st_mtime)
1630 stream = fopen(fname, "r");
1633 psql_error("%s: %s\n", fname, strerror(errno));
1638 /* read file back in */
1641 resetPQExpBuffer(query_buf);
1642 while (fgets(line, sizeof(line), stream) != NULL)
1643 appendPQExpBufferStr(query_buf, line);
1647 psql_error("%s: %s\n", fname, strerror(errno));
1652 replace_history_entry(where_history(),query_buf->data,NULL);
1659 /* remove temp file */
1662 if (remove(fname) == -1)
1664 psql_error("%s: %s\n", fname, strerror(errno));
1677 * Read commands from filename and then them to the main processing loop
1678 * Handler for \i, but can be used for other things as well.
1681 process_file(char *filename)
1690 fd = fopen(filename, "r");
1694 psql_error("%s: %s\n", filename, strerror(errno));
1698 oldfilename = pset.inputfile;
1699 pset.inputfile = filename;
1700 result = MainLoop(fd);
1702 pset.inputfile = oldfilename;
1713 _align2string(enum printFormat in)
1720 case PRINT_UNALIGNED:
1738 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
1742 #ifdef USE_ASSERT_CHECKING
1750 vallen = strlen(value);
1753 if (strcmp(param, "format") == 0)
1757 else if (strncasecmp("unaligned", value, vallen) == 0)
1758 popt->topt.format = PRINT_UNALIGNED;
1759 else if (strncasecmp("aligned", value, vallen) == 0)
1760 popt->topt.format = PRINT_ALIGNED;
1761 else if (strncasecmp("html", value, vallen) == 0)
1762 popt->topt.format = PRINT_HTML;
1763 else if (strncasecmp("latex", value, vallen) == 0)
1764 popt->topt.format = PRINT_LATEX;
1767 psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n");
1772 printf(gettext("Output format is %s.\n"), _align2string(popt->topt.format));
1775 /* set border style/width */
1776 else if (strcmp(param, "border") == 0)
1779 popt->topt.border = atoi(value);
1782 printf(gettext("Border style is %d.\n"), popt->topt.border);
1785 /* set expanded/vertical mode */
1786 else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
1788 popt->topt.expanded = !popt->topt.expanded;
1790 printf(popt->topt.expanded
1791 ? gettext("Expanded display is on.\n")
1792 : gettext("Expanded display is off.\n"));
1796 else if (strcmp(param, "null") == 0)
1800 free(popt->nullPrint);
1801 popt->nullPrint = xstrdup(value);
1804 printf(gettext("Null display is '%s'.\n"), popt->nullPrint ? popt->nullPrint : "");
1807 /* field separator for unaligned text */
1808 else if (strcmp(param, "fieldsep") == 0)
1812 free(popt->topt.fieldSep);
1813 popt->topt.fieldSep = xstrdup(value);
1816 printf(gettext("Field separator is '%s'.\n"), popt->topt.fieldSep);
1819 /* record separator for unaligned text */
1820 else if (strcmp(param, "recordsep") == 0)
1824 free(popt->topt.recordSep);
1825 popt->topt.recordSep = xstrdup(value);
1829 if (strcmp(popt->topt.recordSep, "\n") == 0)
1830 printf(gettext("Record separator is <newline>."));
1832 printf(gettext("Record separator is '%s'.\n"), popt->topt.recordSep);
1836 /* toggle between full and barebones format */
1837 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
1839 popt->topt.tuples_only = !popt->topt.tuples_only;
1842 if (popt->topt.tuples_only)
1843 puts(gettext("Showing only tuples."));
1845 puts(gettext("Tuples only is off."));
1849 /* set title override */
1850 else if (strcmp(param, "title") == 0)
1856 popt->title = xstrdup(value);
1861 printf(gettext("Title is \"%s\".\n"), popt->title);
1863 printf(gettext("Title is unset.\n"));
1867 /* set HTML table tag options */
1868 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
1870 free(popt->topt.tableAttr);
1872 popt->topt.tableAttr = NULL;
1874 popt->topt.tableAttr = xstrdup(value);
1878 if (popt->topt.tableAttr)
1879 printf(gettext("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
1881 printf(gettext("Table attributes unset.\n"));
1885 /* toggle use of pager */
1886 else if (strcmp(param, "pager") == 0)
1888 if (value && strcasecmp(value, "always") == 0)
1889 popt->topt.pager = 2;
1890 else if (popt->topt.pager == 1)
1891 popt->topt.pager = 0;
1893 popt->topt.pager = 1;
1896 if (popt->topt.pager == 1)
1897 puts(gettext("Using pager is on."));
1898 else if (popt->topt.pager == 2)
1899 puts(gettext("Using pager is always."));
1901 puts(gettext("Using pager is off."));
1905 /* disable "(x rows)" footer */
1906 else if (strcmp(param, "footer") == 0)
1908 popt->default_footer = !popt->default_footer;
1911 if (popt->default_footer)
1912 puts(gettext("Default footer is on."));
1914 puts(gettext("Default footer is off."));
1920 psql_error("\\pset: unknown option: %s\n", param);
1929 #define DEFAULT_SHELL "/bin/sh"
1932 do_shell(const char *command)
1939 const char *shellName;
1941 shellName = getenv("SHELL");
1942 if (shellName == NULL)
1943 shellName = DEFAULT_SHELL;
1945 sys = malloc(strlen(shellName) + 16);
1948 psql_error("out of memory\n");
1949 if (pset.cur_cmd_interactive)
1954 sprintf(sys, "exec %s", shellName);
1955 result = system(sys);
1959 result = system(command);
1961 if (result == 127 || result == -1)
1963 psql_error("\\!: failed\n");