2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2005, PostgreSQL Global Development Group
6 * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.157 2005/12/23 01:16:38 tgl Exp $
8 #include "postgres_fe.h"
11 #ifdef WIN32_CLIENT_ONLY /* needed for BCC */
20 #include <sys/types.h> /* for umask() */
21 #include <sys/stat.h> /* for stat() */
22 #include <fcntl.h> /* open() flags */
23 #include <unistd.h> /* for geteuid(), getpid(), stat() */
29 #ifndef WIN32_CLIENT_ONLY
30 #include <sys/types.h> /* for umask() */
31 #include <sys/stat.h> /* for stat() */
36 #include "pqexpbuffer.h"
37 #include "dumputils.h"
44 #include "large_obj.h"
49 #include "variables.h"
50 #include "mb/pg_wchar.h"
53 /* functions for use in this file */
54 static backslashResult exec_command(const char *cmd,
55 PsqlScanState scan_state,
56 PQExpBuffer query_buf);
57 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
58 static bool do_connect(const char *new_dbname, const char *new_user);
59 static bool do_shell(const char *command);
65 * Handles all the different commands that start with '\',
66 * ordinarily called by MainLoop().
68 * scan_state is a lexer working state that is set to continue scanning
69 * just after the '\'. The lexer is advanced past the command and all
70 * arguments on return.
72 * 'query_buf' contains the query-so-far, which may be modified by
73 * execution of the backslash command (for example, \r clears it).
74 * query_buf can be NULL if there is no query so far.
76 * Returns a status code indicating what action is desired, see command.h.
81 HandleSlashCmds(PsqlScanState scan_state,
82 PQExpBuffer query_buf)
84 backslashResult status = PSQL_CMD_SKIP_LINE;
88 psql_assert(scan_state);
90 /* Parse off the command name */
91 cmd = psql_scan_slash_command(scan_state);
93 /* And try to execute it */
94 status = exec_command(cmd, scan_state, query_buf);
96 if (status == PSQL_CMD_UNKNOWN && strlen(cmd) > 1)
99 * If the command was not recognized, try to parse it as a one-letter
100 * command with immediately following argument (a still-supported, but
101 * no longer encouraged, syntax).
105 /* don't change cmd until we know it's okay */
109 psql_scan_slash_pushback(scan_state, cmd + 1);
111 status = exec_command(new_cmd, scan_state, query_buf);
113 if (status != PSQL_CMD_UNKNOWN)
115 /* adjust cmd for possible messages below */
120 if (status == PSQL_CMD_UNKNOWN)
122 if (pset.cur_cmd_interactive)
123 fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);
125 psql_error("invalid command \\%s\n", cmd);
126 status = PSQL_CMD_ERROR;
129 if (status != PSQL_CMD_ERROR)
131 /* eat any remaining arguments after a valid command */
132 /* note we suppress evaluation of backticks here */
133 while ((arg = psql_scan_slash_option(scan_state,
134 OT_VERBATIM, NULL, false)))
136 psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
142 /* silently throw away rest of line after an erroneous command */
143 while ((arg = psql_scan_slash_option(scan_state,
144 OT_WHOLE_LINE, NULL, false)))
148 /* if there is a trailing \\, swallow it */
149 psql_scan_slash_command_end(scan_state);
157 * Subroutine to actually try to execute a backslash command.
159 static backslashResult
160 exec_command(const char *cmd,
161 PsqlScanState scan_state,
162 PQExpBuffer query_buf)
164 bool success = true; /* indicate here if the command ran ok or
166 bool quiet = QUIET();
167 backslashResult status = PSQL_CMD_SKIP_LINE;
170 * \a -- toggle field alignment This makes little sense but we keep it
173 if (strcmp(cmd, "a") == 0)
175 if (pset.popt.topt.format != PRINT_ALIGNED)
176 success = do_pset("format", "aligned", &pset.popt, quiet);
178 success = do_pset("format", "unaligned", &pset.popt, quiet);
181 /* \C -- override table title (formerly change HTML caption) */
182 else if (strcmp(cmd, "C") == 0)
184 char *opt = psql_scan_slash_option(scan_state,
185 OT_NORMAL, NULL, true);
187 success = do_pset("title", opt, &pset.popt, quiet);
192 * \c or \connect -- connect to new database or as different user
194 * \c foo bar connect to db "foo" as user "bar"
195 * \c foo [-] connect to db "foo" as current user
196 * \c - bar connect to current db as user "bar"
197 * \c connect to default db as default user
200 else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
208 * Ideally we should treat the arguments as SQL identifiers. But for
209 * backwards compatibility with 7.2 and older pg_dump files, we have
210 * to take unquoted arguments verbatim (don't downcase them). For now,
211 * double-quoted arguments may be stripped of double quotes (as if SQL
212 * identifiers). By 7.4 or so, pg_dump files can be expected to
213 * double-quote all mixed-case \connect arguments, and then we can get
214 * rid of OT_SQLIDHACK.
216 opt1 = psql_scan_slash_option(scan_state,
217 OT_SQLIDHACK, &opt1q, true);
218 opt2 = psql_scan_slash_option(scan_state,
219 OT_SQLIDHACK, &opt2q, true);
223 success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
224 !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2);
226 /* gave database name */
227 success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1, "");
229 /* connect to default db as default user */
230 success = do_connect(NULL, NULL);
237 else if (strcmp(cmd, "cd") == 0)
239 char *opt = psql_scan_slash_option(scan_state,
240 OT_NORMAL, NULL, true);
250 pw = getpwuid(geteuid());
253 psql_error("could not get home directory: %s\n", strerror(errno));
260 * On Windows, 'cd' without arguments prints the current
261 * directory, so if someone wants to code this here instead...
267 if (chdir(dir) == -1)
269 psql_error("\\%s: could not change directory to \"%s\": %s\n",
270 cmd, dir, strerror(errno));
276 pset.dirname = pg_strdup(dir);
277 canonicalize_path(pset.dirname);
284 else if (pg_strcasecmp(cmd, "copy") == 0)
286 char *opt = psql_scan_slash_option(scan_state,
287 OT_WHOLE_LINE, NULL, false);
289 success = do_copy(opt);
294 else if (strcmp(cmd, "copyright") == 0)
298 else if (cmd[0] == 'd')
303 /* We don't do SQLID reduction on the pattern yet */
304 pattern = psql_scan_slash_option(scan_state,
305 OT_NORMAL, NULL, true);
307 show_verbose = strchr(cmd, '+') ? true : false;
314 success = describeTableDetails(pattern, show_verbose);
316 /* standard listing of interesting things */
317 success = listTables("tvs", NULL, show_verbose);
320 success = describeAggregates(pattern, show_verbose);
323 success = describeTablespaces(pattern, show_verbose);
326 success = listConversions(pattern);
329 success = listCasts(pattern);
332 success = objectDescription(pattern);
335 success = listDomains(pattern);
338 success = describeFunctions(pattern, show_verbose);
341 /* no longer distinct from \du */
342 success = describeRoles(pattern);
345 success = do_lo_list();
348 success = listSchemas(pattern, show_verbose);
351 success = describeOperators(pattern);
354 success = permissionsList(pattern);
357 success = describeTypes(pattern, show_verbose);
364 success = listTables(&cmd[1], pattern, show_verbose);
367 success = describeRoles(pattern);
371 status = PSQL_CMD_UNKNOWN;
380 * \e or \edit -- edit the current query buffer (or a file and make it the
383 else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
389 psql_error("no query buffer\n");
390 status = PSQL_CMD_ERROR;
394 fname = psql_scan_slash_option(scan_state,
395 OT_NORMAL, NULL, true);
396 expand_tilde(&fname);
398 canonicalize_path(fname);
399 status = do_edit(fname, query_buf) ? PSQL_CMD_NEWEDIT : PSQL_CMD_ERROR;
404 /* \echo and \qecho */
405 else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
409 bool no_newline = false;
413 if (strcmp(cmd, "qecho") == 0)
414 fout = pset.queryFout;
418 while ((value = psql_scan_slash_option(scan_state,
419 OT_NORMAL, "ed, false)))
421 if (!quoted && strcmp(value, "-n") == 0)
437 /* \encoding -- set/show client side encoding */
438 else if (strcmp(cmd, "encoding") == 0)
440 char *encoding = psql_scan_slash_option(scan_state,
441 OT_NORMAL, NULL, false);
446 puts(pg_encoding_to_char(pset.encoding));
451 if (PQsetClientEncoding(pset.db, encoding) == -1)
452 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
455 /* save encoding info into psql internal data */
456 pset.encoding = PQclientEncoding(pset.db);
457 pset.popt.topt.encoding = pset.encoding;
458 SetVariable(pset.vars, "ENCODING",
459 pg_encoding_to_char(pset.encoding));
465 /* \f -- change field separator */
466 else if (strcmp(cmd, "f") == 0)
468 char *fname = psql_scan_slash_option(scan_state,
469 OT_NORMAL, NULL, false);
471 success = do_pset("fieldsep", fname, &pset.popt, quiet);
475 /* \g means send query */
476 else if (strcmp(cmd, "g") == 0)
478 char *fname = psql_scan_slash_option(scan_state,
479 OT_FILEPIPE, NULL, false);
485 expand_tilde(&fname);
486 pset.gfname = pg_strdup(fname);
489 status = PSQL_CMD_SEND;
493 else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
495 char *opt = psql_scan_slash_option(scan_state,
496 OT_WHOLE_LINE, NULL, false);
498 helpSQL(opt, pset.popt.topt.pager);
503 else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
505 if (pset.popt.topt.format != PRINT_HTML)
506 success = do_pset("format", "html", &pset.popt, quiet);
508 success = do_pset("format", "aligned", &pset.popt, quiet);
512 /* \i is include file */
513 else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
515 char *fname = psql_scan_slash_option(scan_state,
516 OT_NORMAL, NULL, true);
520 psql_error("\\%s: missing required argument\n", cmd);
525 expand_tilde(&fname);
526 success = (process_file(fname) == EXIT_SUCCESS);
531 /* \l is list databases */
532 else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
533 success = listAllDbs(false);
534 else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
535 success = listAllDbs(true);
538 * large object things
540 else if (strncmp(cmd, "lo_", 3) == 0)
545 opt1 = psql_scan_slash_option(scan_state,
546 OT_NORMAL, NULL, true);
547 opt2 = psql_scan_slash_option(scan_state,
548 OT_NORMAL, NULL, true);
550 if (strcmp(cmd + 3, "export") == 0)
554 psql_error("\\%s: missing required argument\n", cmd);
560 success = do_lo_export(opt1, opt2);
564 else if (strcmp(cmd + 3, "import") == 0)
568 psql_error("\\%s: missing required argument\n", cmd);
574 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 = PSQL_CMD_UNKNOWN;
600 /* \o -- set query output */
601 else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
603 char *fname = psql_scan_slash_option(scan_state,
604 OT_FILEPIPE, NULL, true);
606 expand_tilde(&fname);
607 success = setQFout(fname);
611 /* \p prints the current query buffer */
612 else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
614 if (query_buf && query_buf->len > 0)
615 puts(query_buf->data);
617 puts(_("Query buffer is empty."));
621 /* \password -- set user password */
622 else if (strcmp(cmd, "password") == 0)
627 pw1 = simple_prompt("Enter new password: ", 100, false);
628 pw2 = simple_prompt("Enter it again: ", 100, false);
630 if (strcmp(pw1, pw2) != 0)
632 fprintf(stderr, _("Passwords didn't match.\n"));
637 char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
639 char *encrypted_password;
644 user = PQuser(pset.db);
646 encrypted_password = pg_make_encrypted_password(pw1, user);
648 if (!encrypted_password)
650 fprintf(stderr, _("Password encryption failed.\n"));
658 initPQExpBuffer(&buf);
659 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD '%s';",
660 fmtId(user), encrypted_password);
661 res = PSQLexec(buf.data, false);
662 termPQExpBuffer(&buf);
667 PQfreemem(encrypted_password);
675 /* \pset -- set printing parameters */
676 else if (strcmp(cmd, "pset") == 0)
678 char *opt0 = psql_scan_slash_option(scan_state,
679 OT_NORMAL, NULL, false);
680 char *opt1 = psql_scan_slash_option(scan_state,
681 OT_NORMAL, NULL, false);
685 psql_error("\\%s: missing required argument\n", cmd);
689 success = do_pset(opt0, opt1, &pset.popt, quiet);
696 else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
697 status = PSQL_CMD_TERMINATE;
699 /* reset(clear) the buffer */
700 else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
702 resetPQExpBuffer(query_buf);
703 psql_scan_reset(scan_state);
705 puts(_("Query buffer reset (cleared)."));
708 /* \s save history in a file or show it on the screen */
709 else if (strcmp(cmd, "s") == 0)
711 char *fname = psql_scan_slash_option(scan_state,
712 OT_NORMAL, NULL, true);
714 expand_tilde(&fname);
715 /* This scrolls off the screen when using /dev/tty */
716 success = saveHistory(fname ? fname : "/dev/tty");
718 if (success && !quiet && fname)
719 printf(gettext("Wrote history to file \"%s/%s\".\n"),
720 pset.dirname ? pset.dirname : ".", fname);
726 /* \set -- generalized set variable/option command */
727 else if (strcmp(cmd, "set") == 0)
729 char *opt0 = psql_scan_slash_option(scan_state,
730 OT_NORMAL, NULL, false);
734 /* list all variables */
735 PrintVariables(pset.vars);
741 * Set variable to the concatenation of the arguments.
746 opt = psql_scan_slash_option(scan_state,
747 OT_NORMAL, NULL, false);
748 newval = pg_strdup(opt ? opt : "");
751 while ((opt = psql_scan_slash_option(scan_state,
752 OT_NORMAL, NULL, false)))
754 newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
757 psql_error("out of memory\n");
764 if (SetVariable(pset.vars, opt0, newval))
766 /* Check for special variables */
767 if (strcmp(opt0, "VERBOSITY") == 0)
768 SyncVerbosityVariable();
772 psql_error("\\%s: error\n", cmd);
780 /* \t -- turn off headers and row count */
781 else if (strcmp(cmd, "t") == 0)
782 success = do_pset("tuples_only", NULL, &pset.popt, quiet);
785 /* \T -- define html <table ...> attributes */
786 else if (strcmp(cmd, "T") == 0)
788 char *value = psql_scan_slash_option(scan_state,
789 OT_NORMAL, NULL, false);
791 success = do_pset("tableattr", value, &pset.popt, quiet);
795 /* \timing -- toggle timing of queries */
796 else if (strcmp(cmd, "timing") == 0)
798 pset.timing = !pset.timing;
802 puts(_("Timing is on."));
804 puts(_("Timing is off."));
809 else if (strcmp(cmd, "unset") == 0)
811 char *opt = psql_scan_slash_option(scan_state,
812 OT_NORMAL, NULL, false);
816 psql_error("\\%s: missing required argument\n", cmd);
819 else if (!SetVariable(pset.vars, opt, NULL))
821 psql_error("\\%s: error\n", cmd);
827 /* \w -- write query buffer to file */
828 else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
831 bool is_pipe = false;
836 psql_error("no query buffer\n");
837 status = PSQL_CMD_ERROR;
841 fname = psql_scan_slash_option(scan_state,
842 OT_FILEPIPE, NULL, true);
843 expand_tilde(&fname);
847 psql_error("\\%s: missing required argument\n", cmd);
855 fd = popen(&fname[1], "w");
859 canonicalize_path(fname);
860 fd = fopen(fname, "w");
864 psql_error("%s: %s\n", fname, strerror(errno));
874 if (query_buf && query_buf->len > 0)
875 fprintf(fd, "%s\n", query_buf->data);
884 psql_error("%s: %s\n", fname, strerror(errno));
892 /* \x -- toggle expanded table representation */
893 else if (strcmp(cmd, "x") == 0)
894 success = do_pset("expanded", NULL, &pset.popt, quiet);
896 /* \z -- list table rights (equivalent to \dp) */
897 else if (strcmp(cmd, "z") == 0)
899 char *pattern = psql_scan_slash_option(scan_state,
900 OT_NORMAL, NULL, true);
902 success = permissionsList(pattern);
907 /* \! -- shell escape */
908 else if (strcmp(cmd, "!") == 0)
910 char *opt = psql_scan_slash_option(scan_state,
911 OT_WHOLE_LINE, NULL, false);
913 success = do_shell(opt);
917 /* \? -- slash command help */
918 else if (strcmp(cmd, "?") == 0)
919 slashUsage(pset.popt.topt.pager);
924 * These commands don't do anything. I just use them to test the parser.
926 else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
931 while ((value = psql_scan_slash_option(scan_state,
932 OT_NORMAL, NULL, true)))
934 fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
941 status = PSQL_CMD_UNKNOWN;
944 status = PSQL_CMD_ERROR;
952 * -- handler for \connect
954 * Connects to a database (new_dbname) as a certain user (new_user).
955 * The new user can be NULL. A db name of "-" is the same as the old one.
956 * (That is, the one currently in pset. But pset.db can also be NULL. A NULL
957 * dbname is handled by libpq.)
958 * Returns true if all ok, false if the new connection couldn't be established.
959 * The old connection will be kept if the session is interactive.
962 do_connect(const char *new_dbname, const char *new_user)
964 PGconn *oldconn = pset.db;
965 const char *dbparam = NULL;
966 const char *userparam = NULL;
967 const char *pwparam = NULL;
968 char *password_prompt = NULL;
969 char *prompted_password = NULL;
971 bool success = false;
973 /* Delete variables (in case we fail before setting them anew) */
976 /* If dbname is "" then use old name, else new one (even if NULL) */
977 if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0)
978 dbparam = PQdb(oldconn);
980 dbparam = new_dbname;
982 /* If user is "" then use the old one */
983 if (new_user && PQuser(oldconn) && strcmp(new_user, "") == 0)
984 userparam = PQuser(oldconn);
986 userparam = new_user;
988 if (userparam == NULL)
989 password_prompt = strdup("Password: ");
992 password_prompt = malloc(strlen(_("Password for user %s: ")) - 2 +
993 strlen(userparam) + 1);
994 sprintf(password_prompt, _("Password for user %s: "), userparam);
997 /* need to prompt for password? */
998 if (pset.getPassword)
999 pwparam = prompted_password = simple_prompt(password_prompt, 100, false);
1002 * Use old password (if any) if no new one given and we are reconnecting
1005 if (!pwparam && oldconn && PQuser(oldconn) && userparam &&
1006 strcmp(PQuser(oldconn), userparam) == 0)
1007 pwparam = PQpass(oldconn);
1012 pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
1013 NULL, NULL, dbparam, userparam, pwparam);
1015 if (PQstatus(pset.db) == CONNECTION_BAD &&
1016 strcmp(PQerrorMessage(pset.db), PQnoPasswordSupplied) == 0 &&
1021 free(prompted_password);
1022 prompted_password = NULL;
1023 pwparam = prompted_password = simple_prompt(password_prompt, 100, false);
1025 } while (need_pass);
1027 free(prompted_password);
1028 free(password_prompt);
1031 * If connection failed, try at least keep the old one. That's probably
1032 * more convenient than just kicking you out of the program.
1034 if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD)
1036 if (pset.cur_cmd_interactive)
1038 psql_error("%s", PQerrorMessage(pset.db));
1042 fputs(_("Previous connection kept\n"), stderr);
1051 * we don't want unpredictable things to happen in scripting mode
1053 psql_error("\\connect: %s", PQerrorMessage(pset.db));
1064 if (userparam != new_user) /* no new user */
1065 printf(_("You are now connected to database \"%s\".\n"), dbparam);
1066 else if (dbparam != new_dbname) /* no new db */
1067 printf(_("You are now connected as new user \"%s\".\n"), new_user);
1070 printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
1071 PQdb(pset.db), PQuser(pset.db));
1080 PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
1082 /* Update variables */
1092 * Make psql's internal variables agree with connection state upon
1093 * establishing a new connection.
1098 /* get stuff from connection */
1099 pset.encoding = PQclientEncoding(pset.db);
1100 pset.popt.topt.encoding = pset.encoding;
1102 SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
1103 SetVariable(pset.vars, "USER", PQuser(pset.db));
1104 SetVariable(pset.vars, "HOST", PQhost(pset.db));
1105 SetVariable(pset.vars, "PORT", PQport(pset.db));
1106 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
1108 /* send stuff to it, too */
1109 SyncVerbosityVariable();
1115 * Clear variables that should be not be set when there is no connection.
1118 UnsyncVariables(void)
1120 SetVariable(pset.vars, "DBNAME", NULL);
1121 SetVariable(pset.vars, "USER", NULL);
1122 SetVariable(pset.vars, "HOST", NULL);
1123 SetVariable(pset.vars, "PORT", NULL);
1124 SetVariable(pset.vars, "ENCODING", NULL);
1128 * Update connection state from VERBOSITY variable
1131 SyncVerbosityVariable(void)
1133 switch (SwitchVariable(pset.vars, "VERBOSITY",
1134 "default", "terse", "verbose", NULL))
1136 case 1: /* default */
1137 pset.verbosity = PQERRORS_DEFAULT;
1140 pset.verbosity = PQERRORS_TERSE;
1142 case 3: /* verbose */
1143 pset.verbosity = PQERRORS_VERBOSE;
1145 default: /* not set or unrecognized value */
1146 pset.verbosity = PQERRORS_DEFAULT;
1150 PQsetErrorVerbosity(pset.db, pset.verbosity);
1155 * do_edit -- handler for \e
1157 * If you do not specify a filename, the current query buffer will be copied
1158 * into a temporary one.
1162 editFile(const char *fname)
1164 const char *editorName;
1170 /* Find an editor to use */
1171 editorName = getenv("PSQL_EDITOR");
1173 editorName = getenv("EDITOR");
1175 editorName = getenv("VISUAL");
1177 editorName = DEFAULT_EDITOR;
1180 * On Unix the EDITOR value should *not* be quoted, since it might include
1181 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
1182 * if necessary. But this policy is not very workable on Windows, due to
1183 * severe brain damage in their command shell plus the fact that standard
1184 * program paths include spaces.
1186 sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
1188 sprintf(sys, "exec %s '%s'", editorName, fname);
1190 sprintf(sys, "%s\"%s\" \"%s\"%s",
1191 SYSTEMQUOTE, editorName, fname, SYSTEMQUOTE);
1193 result = system(sys);
1195 psql_error("could not start editor \"%s\"\n", editorName);
1196 else if (result == 127)
1197 psql_error("could not start /bin/sh\n");
1206 do_edit(const char *filename_arg, PQExpBuffer query_buf)
1208 char fnametmp[MAXPGPATH];
1209 FILE *stream = NULL;
1214 #ifndef WIN32_CLIENT_ONLY
1220 fname = filename_arg;
1223 /* make a temp file to edit */
1225 const char *tmpdir = getenv("TMPDIR");
1230 char tmpdir[MAXPGPATH];
1233 ret = GetTempPath(MAXPGPATH, tmpdir);
1234 if (ret == 0 || ret > MAXPGPATH)
1236 psql_error("cannot locate temporary directory: %s",
1237 !ret ? strerror(errno) : "");
1242 * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
1243 * current directory to the supplied path unless we use only
1244 * backslashes, so we do that.
1248 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1249 "/", (int) getpid());
1251 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1252 "" /* trailing separator already present */ , (int) getpid());
1255 fname = (const char *) fnametmp;
1257 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
1259 stream = fdopen(fd, "w");
1261 if (fd == -1 || !stream)
1263 psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
1268 unsigned int ql = query_buf->len;
1270 if (ql == 0 || query_buf->data[ql - 1] != '\n')
1272 appendPQExpBufferChar(query_buf, '\n');
1276 if (fwrite(query_buf->data, 1, ql, stream) != ql)
1278 psql_error("%s: %s\n", fname, strerror(errno));
1283 else if (fclose(stream) != 0)
1285 psql_error("%s: %s\n", fname, strerror(errno));
1292 #ifndef WIN32_CLIENT_ONLY
1293 if (!error && stat(fname, &before) != 0)
1295 psql_error("%s: %s\n", fname, strerror(errno));
1302 error = !editFile(fname);
1304 #ifndef WIN32_CLIENT_ONLY
1305 if (!error && stat(fname, &after) != 0)
1307 psql_error("%s: %s\n", fname, strerror(errno));
1311 if (!error && before.st_mtime != after.st_mtime)
1317 stream = fopen(fname, PG_BINARY_R);
1320 psql_error("%s: %s\n", fname, strerror(errno));
1325 /* read file back in */
1328 resetPQExpBuffer(query_buf);
1329 while (fgets(line, sizeof(line), stream) != NULL)
1330 appendPQExpBufferStr(query_buf, line);
1334 psql_error("%s: %s\n", fname, strerror(errno));
1339 #ifdef HAVE_REPLACE_HISTORY_ENTRY
1341 replace_history_entry(where_history(), query_buf->data, NULL);
1343 add_history(query_buf->data);
1351 /* remove temp file */
1354 if (remove(fname) == -1)
1356 psql_error("%s: %s\n", fname, strerror(errno));
1369 * Read commands from filename and then them to the main processing loop
1370 * Handler for \i, but can be used for other things as well. Returns
1371 * MainLoop() error code.
1374 process_file(char *filename)
1381 return EXIT_FAILURE;
1383 canonicalize_path(filename);
1384 fd = fopen(filename, PG_BINARY_R);
1388 psql_error("%s: %s\n", filename, strerror(errno));
1389 return EXIT_FAILURE;
1392 oldfilename = pset.inputfile;
1393 pset.inputfile = filename;
1394 result = MainLoop(fd);
1396 pset.inputfile = oldfilename;
1407 _align2string(enum printFormat in)
1414 case PRINT_UNALIGNED:
1426 case PRINT_TROFF_MS:
1435 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
1442 vallen = strlen(value);
1445 if (strcmp(param, "format") == 0)
1449 else if (pg_strncasecmp("unaligned", value, vallen) == 0)
1450 popt->topt.format = PRINT_UNALIGNED;
1451 else if (pg_strncasecmp("aligned", value, vallen) == 0)
1452 popt->topt.format = PRINT_ALIGNED;
1453 else if (pg_strncasecmp("html", value, vallen) == 0)
1454 popt->topt.format = PRINT_HTML;
1455 else if (pg_strncasecmp("latex", value, vallen) == 0)
1456 popt->topt.format = PRINT_LATEX;
1457 else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
1458 popt->topt.format = PRINT_TROFF_MS;
1461 psql_error("\\pset: allowed formats are unaligned, aligned, html, latex, troff-ms\n");
1466 printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
1469 /* set border style/width */
1470 else if (strcmp(param, "border") == 0)
1473 popt->topt.border = atoi(value);
1476 printf(_("Border style is %d.\n"), popt->topt.border);
1479 /* set expanded/vertical mode */
1480 else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
1482 popt->topt.expanded = !popt->topt.expanded;
1484 printf(popt->topt.expanded
1485 ? _("Expanded display is on.\n")
1486 : _("Expanded display is off.\n"));
1489 /* locale-aware numeric output */
1490 else if (strcmp(param, "numericlocale") == 0)
1492 popt->topt.numericLocale = !popt->topt.numericLocale;
1495 if (popt->topt.numericLocale)
1496 puts(_("Showing locale-adjusted numeric output."));
1498 puts(_("Locale-adjusted numeric output is off."));
1503 else if (strcmp(param, "null") == 0)
1507 free(popt->nullPrint);
1508 popt->nullPrint = pg_strdup(value);
1511 printf(_("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : "");
1514 /* field separator for unaligned text */
1515 else if (strcmp(param, "fieldsep") == 0)
1519 free(popt->topt.fieldSep);
1520 popt->topt.fieldSep = pg_strdup(value);
1523 printf(_("Field separator is \"%s\".\n"), popt->topt.fieldSep);
1526 /* record separator for unaligned text */
1527 else if (strcmp(param, "recordsep") == 0)
1531 free(popt->topt.recordSep);
1532 popt->topt.recordSep = pg_strdup(value);
1536 if (strcmp(popt->topt.recordSep, "\n") == 0)
1537 printf(_("Record separator is <newline>."));
1539 printf(_("Record separator is \"%s\".\n"), popt->topt.recordSep);
1543 /* toggle between full and tuples-only format */
1544 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
1546 popt->topt.tuples_only = !popt->topt.tuples_only;
1549 if (popt->topt.tuples_only)
1550 puts(_("Showing only tuples."));
1552 puts(_("Tuples only is off."));
1556 /* set title override */
1557 else if (strcmp(param, "title") == 0)
1563 popt->title = pg_strdup(value);
1568 printf(_("Title is \"%s\".\n"), popt->title);
1570 printf(_("Title is unset.\n"));
1574 /* set HTML table tag options */
1575 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
1577 free(popt->topt.tableAttr);
1579 popt->topt.tableAttr = NULL;
1581 popt->topt.tableAttr = pg_strdup(value);
1585 if (popt->topt.tableAttr)
1586 printf(_("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
1588 printf(_("Table attributes unset.\n"));
1592 /* toggle use of pager */
1593 else if (strcmp(param, "pager") == 0)
1595 if (value && pg_strcasecmp(value, "always") == 0)
1596 popt->topt.pager = 2;
1597 else if (popt->topt.pager == 1)
1598 popt->topt.pager = 0;
1600 popt->topt.pager = 1;
1603 if (popt->topt.pager == 1)
1604 puts(_("Pager is used for long output."));
1605 else if (popt->topt.pager == 2)
1606 puts(_("Pager is always used."));
1608 puts(_("Pager usage is off."));
1612 /* disable "(x rows)" footer */
1613 else if (strcmp(param, "footer") == 0)
1615 popt->default_footer = !popt->default_footer;
1618 if (popt->default_footer)
1619 puts(_("Default footer is on."));
1621 puts(_("Default footer is off."));
1627 psql_error("\\pset: unknown option: %s\n", param);
1637 #define DEFAULT_SHELL "/bin/sh"
1640 * CMD.EXE is in different places in different Win32 releases so we
1641 * have to rely on the path to find it.
1643 #define DEFAULT_SHELL "cmd.exe"
1647 do_shell(const char *command)
1654 const char *shellName;
1656 shellName = getenv("SHELL");
1658 if (shellName == NULL)
1659 shellName = getenv("COMSPEC");
1661 if (shellName == NULL)
1662 shellName = DEFAULT_SHELL;
1664 sys = pg_malloc(strlen(shellName) + 16);
1667 /* See EDITOR handling comment for an explaination */
1668 "exec %s", shellName);
1671 /* See EDITOR handling comment for an explaination */
1672 "%s\"%s\"%s", SYSTEMQUOTE, shellName, SYSTEMQUOTE);
1674 result = system(sys);
1678 result = system(command);
1680 if (result == 127 || result == -1)
1682 psql_error("\\!: failed\n");