1 /*
2 * psql - the PostgreSQL interactive terminal
3 *
4 * Copyright (c) 2000-2017, PostgreSQL Global Development Group
5 *
6 * src/bin/psql/command.c
7 */
8 #include "postgres_fe.h"
9 #include "command.h"
10
11 #include <ctype.h>
12 #include <time.h>
13 #include <pwd.h>
14 #include <utime.h>
15 #ifndef WIN32
16 #include <sys/stat.h> /* for stat() */
17 #include <fcntl.h> /* open() flags */
18 #include <unistd.h> /* for geteuid(), getpid(), stat() */
19 #else
20 #include <win32.h>
21 #include <io.h>
22 #include <fcntl.h>
23 #include <direct.h>
24 #include <sys/stat.h> /* for stat() */
25 #endif
26
27 #include "catalog/pg_class.h"
28 #include "portability/instr_time.h"
29
30 #include "libpq-fe.h"
31 #include "pqexpbuffer.h"
32 #include "fe_utils/string_utils.h"
33
34 #include "common.h"
35 #include "copy.h"
36 #include "crosstabview.h"
37 #include "describe.h"
38 #include "help.h"
39 #include "input.h"
40 #include "large_obj.h"
41 #include "mainloop.h"
42 #include "fe_utils/print.h"
43 #include "psqlscanslash.h"
44 #include "settings.h"
45 #include "variables.h"
46
47 /*
48 * Editable database object types.
49 */
50 typedef enum EditableObjectType
51 {
52 EditableFunction,
53 EditableView
54 } EditableObjectType;
55
56 /* local function declarations */
57 static backslashResult exec_command(const char *cmd,
58 PsqlScanState scan_state,
59 ConditionalStack cstack,
60 PQExpBuffer query_buf,
61 PQExpBuffer previous_buf);
62 static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch);
63 static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch);
64 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
65 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
66 const char *cmd);
67 static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
68 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
69 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
70 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
71 static backslashResult exec_command_d(PsqlScanState scan_state, bool active_branch,
72 const char *cmd);
73 static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
74 PQExpBuffer query_buf, PQExpBuffer previous_buf);
75 static backslashResult exec_command_ef(PsqlScanState scan_state, bool active_branch,
76 PQExpBuffer query_buf);
77 static backslashResult exec_command_ev(PsqlScanState scan_state, bool active_branch,
78 PQExpBuffer query_buf);
79 static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
80 const char *cmd);
81 static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
82 PQExpBuffer query_buf);
83 static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
84 PQExpBuffer query_buf);
85 static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
86 PQExpBuffer query_buf);
87 static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch);
88 static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch);
89 static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
90 static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
91 const char *cmd);
92 static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
93 static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
94 static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
95 static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
96 static backslashResult exec_command_include(PsqlScanState scan_state, bool active_branch,
97 const char *cmd);
98 static backslashResult exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
99 PQExpBuffer query_buf);
100 static backslashResult exec_command_list(PsqlScanState scan_state, bool active_branch,
101 const char *cmd);
102 static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_branch,
103 const char *cmd);
104 static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch);
105 static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch,
106 PQExpBuffer query_buf, PQExpBuffer previous_buf);
107 static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch);
108 static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch,
109 const char *cmd);
110 static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_branch);
111 static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
112 static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
113 PQExpBuffer query_buf);
114 static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
115 static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
116 static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
117 const char *cmd);
118 static backslashResult exec_command_sf(PsqlScanState scan_state, bool active_branch,
119 const char *cmd);
120 static backslashResult exec_command_sv(PsqlScanState scan_state, bool active_branch,
121 const char *cmd);
122 static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
123 static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
124 static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
125 static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
126 const char *cmd);
127 static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
128 const char *cmd,
129 PQExpBuffer query_buf, PQExpBuffer previous_buf);
130 static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch,
131 PQExpBuffer query_buf, PQExpBuffer previous_buf);
132 static backslashResult exec_command_x(PsqlScanState scan_state, bool active_branch);
133 static backslashResult exec_command_z(PsqlScanState scan_state, bool active_branch);
134 static backslashResult exec_command_shell_escape(PsqlScanState scan_state, bool active_branch);
135 static backslashResult exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch);
136 static char *read_connect_arg(PsqlScanState scan_state);
137 static PQExpBuffer gather_boolean_expression(PsqlScanState scan_state);
138 static bool is_true_boolean_expression(PsqlScanState scan_state, const char *name);
139 static void ignore_boolean_expression(PsqlScanState scan_state);
140 static void ignore_slash_options(PsqlScanState scan_state);
141 static void ignore_slash_filepipe(PsqlScanState scan_state);
142 static void ignore_slash_whole_line(PsqlScanState scan_state);
143 static bool is_branching_command(const char *cmd);
144 static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
145 PQExpBuffer query_buf);
146 static void discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
147 PQExpBuffer query_buf);
148 static void copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf);
149 static bool do_connect(enum trivalue reuse_previous_specification,
150 char *dbname, char *user, char *host, char *port);
151 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
152 int lineno, bool *edited);
153 static bool do_shell(const char *command);
154 static bool do_watch(PQExpBuffer query_buf, double sleep);
155 static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
156 Oid *obj_oid);
157 static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
158 PQExpBuffer buf);
159 static int strip_lineno_from_objdesc(char *obj);
160 static int count_lines_in_buf(PQExpBuffer buf);
161 static void print_with_linenumbers(FILE *output, char *lines,
162 const char *header_keyword);
163 static void minimal_error_message(PGresult *res);
164
165 static void printSSLInfo(void);
166 static bool printPsetInfo(const char *param, struct printQueryOpt *popt);
167 static char *pset_value_string(const char *param, struct printQueryOpt *popt);
168
169 #ifdef WIN32
170 static void checkWin32Codepage(void);
171 #endif
172
173
174
175 /*----------
176 * HandleSlashCmds:
177 *
178 * Handles all the different commands that start with '\'.
179 * Ordinarily called by MainLoop().
180 *
181 * scan_state is a lexer working state that is set to continue scanning
182 * just after the '\'. The lexer is advanced past the command and all
183 * arguments on return.
184 *
185 * cstack is the current \if stack state. This will be examined, and
186 * possibly modified by conditional commands.
187 *
188 * query_buf contains the query-so-far, which may be modified by
189 * execution of the backslash command (for example, \r clears it).
190 *
191 * previous_buf contains the query most recently sent to the server
192 * (empty if none yet). This should not be modified here, but some
193 * commands copy its content into query_buf.
194 *
195 * query_buf and previous_buf will be NULL when executing a "-c"
196 * command-line option.
197 *
198 * Returns a status code indicating what action is desired, see command.h.
199 *----------
200 */
201
202 backslashResult
HandleSlashCmds(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)203 HandleSlashCmds(PsqlScanState scan_state,
204 ConditionalStack cstack,
205 PQExpBuffer query_buf,
206 PQExpBuffer previous_buf)
207 {
208 backslashResult status;
209 char *cmd;
210 char *arg;
211
212 Assert(scan_state != NULL);
213 Assert(cstack != NULL);
214
215 /* Parse off the command name */
216 cmd = psql_scan_slash_command(scan_state);
217
218 /* And try to execute it */
219 status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
220
221 if (status == PSQL_CMD_UNKNOWN)
222 {
223 if (pset.cur_cmd_interactive)
224 psql_error("Invalid command \\%s. Try \\? for help.\n", cmd);
225 else
226 psql_error("invalid command \\%s\n", cmd);
227 status = PSQL_CMD_ERROR;
228 }
229
230 if (status != PSQL_CMD_ERROR)
231 {
232 /*
233 * Eat any remaining arguments after a valid command. We want to
234 * suppress evaluation of backticks in this situation, so transiently
235 * push an inactive conditional-stack entry.
236 */
237 bool active_branch = conditional_active(cstack);
238
239 conditional_stack_push(cstack, IFSTATE_IGNORED);
240 while ((arg = psql_scan_slash_option(scan_state,
241 OT_NORMAL, NULL, false)))
242 {
243 if (active_branch)
244 psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
245 free(arg);
246 }
247 conditional_stack_pop(cstack);
248 }
249 else
250 {
251 /* silently throw away rest of line after an erroneous command */
252 while ((arg = psql_scan_slash_option(scan_state,
253 OT_WHOLE_LINE, NULL, false)))
254 free(arg);
255 }
256
257 /* if there is a trailing \\, swallow it */
258 psql_scan_slash_command_end(scan_state);
259
260 free(cmd);
261
262 /* some commands write to queryFout, so make sure output is sent */
263 fflush(pset.queryFout);
264
265 return status;
266 }
267
268
269 /*
270 * Subroutine to actually try to execute a backslash command.
271 *
272 * The typical "success" result code is PSQL_CMD_SKIP_LINE, although some
273 * commands return something else. Failure results are PSQL_CMD_ERROR,
274 * unless PSQL_CMD_UNKNOWN is more appropriate.
275 */
276 static backslashResult
exec_command(const char * cmd,PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)277 exec_command(const char *cmd,
278 PsqlScanState scan_state,
279 ConditionalStack cstack,
280 PQExpBuffer query_buf,
281 PQExpBuffer previous_buf)
282 {
283 backslashResult status;
284 bool active_branch = conditional_active(cstack);
285
286 /*
287 * In interactive mode, warn when we're ignoring a command within a false
288 * \if-branch. But we continue on, so as to parse and discard the right
289 * amount of parameter text. Each individual backslash command subroutine
290 * is responsible for doing nothing after discarding appropriate
291 * arguments, if !active_branch.
292 */
293 if (pset.cur_cmd_interactive && !active_branch &&
294 !is_branching_command(cmd))
295 {
296 psql_error("\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block\n",
297 cmd);
298 }
299
300 if (strcmp(cmd, "a") == 0)
301 status = exec_command_a(scan_state, active_branch);
302 else if (strcmp(cmd, "C") == 0)
303 status = exec_command_C(scan_state, active_branch);
304 else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
305 status = exec_command_connect(scan_state, active_branch);
306 else if (strcmp(cmd, "cd") == 0)
307 status = exec_command_cd(scan_state, active_branch, cmd);
308 else if (strcmp(cmd, "conninfo") == 0)
309 status = exec_command_conninfo(scan_state, active_branch);
310 else if (pg_strcasecmp(cmd, "copy") == 0)
311 status = exec_command_copy(scan_state, active_branch);
312 else if (strcmp(cmd, "copyright") == 0)
313 status = exec_command_copyright(scan_state, active_branch);
314 else if (strcmp(cmd, "crosstabview") == 0)
315 status = exec_command_crosstabview(scan_state, active_branch);
316 else if (cmd[0] == 'd')
317 status = exec_command_d(scan_state, active_branch, cmd);
318 else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
319 status = exec_command_edit(scan_state, active_branch,
320 query_buf, previous_buf);
321 else if (strcmp(cmd, "ef") == 0)
322 status = exec_command_ef(scan_state, active_branch, query_buf);
323 else if (strcmp(cmd, "ev") == 0)
324 status = exec_command_ev(scan_state, active_branch, query_buf);
325 else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
326 status = exec_command_echo(scan_state, active_branch, cmd);
327 else if (strcmp(cmd, "elif") == 0)
328 status = exec_command_elif(scan_state, cstack, query_buf);
329 else if (strcmp(cmd, "else") == 0)
330 status = exec_command_else(scan_state, cstack, query_buf);
331 else if (strcmp(cmd, "endif") == 0)
332 status = exec_command_endif(scan_state, cstack, query_buf);
333 else if (strcmp(cmd, "encoding") == 0)
334 status = exec_command_encoding(scan_state, active_branch);
335 else if (strcmp(cmd, "errverbose") == 0)
336 status = exec_command_errverbose(scan_state, active_branch);
337 else if (strcmp(cmd, "f") == 0)
338 status = exec_command_f(scan_state, active_branch);
339 else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
340 status = exec_command_g(scan_state, active_branch, cmd);
341 else if (strcmp(cmd, "gexec") == 0)
342 status = exec_command_gexec(scan_state, active_branch);
343 else if (strcmp(cmd, "gset") == 0)
344 status = exec_command_gset(scan_state, active_branch);
345 else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
346 status = exec_command_help(scan_state, active_branch);
347 else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
348 status = exec_command_html(scan_state, active_branch);
349 else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 ||
350 strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
351 status = exec_command_include(scan_state, active_branch, cmd);
352 else if (strcmp(cmd, "if") == 0)
353 status = exec_command_if(scan_state, cstack, query_buf);
354 else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
355 strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
356 status = exec_command_list(scan_state, active_branch, cmd);
357 else if (strncmp(cmd, "lo_", 3) == 0)
358 status = exec_command_lo(scan_state, active_branch, cmd);
359 else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
360 status = exec_command_out(scan_state, active_branch);
361 else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
362 status = exec_command_print(scan_state, active_branch,
363 query_buf, previous_buf);
364 else if (strcmp(cmd, "password") == 0)
365 status = exec_command_password(scan_state, active_branch);
366 else if (strcmp(cmd, "prompt") == 0)
367 status = exec_command_prompt(scan_state, active_branch, cmd);
368 else if (strcmp(cmd, "pset") == 0)
369 status = exec_command_pset(scan_state, active_branch);
370 else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
371 status = exec_command_quit(scan_state, active_branch);
372 else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
373 status = exec_command_reset(scan_state, active_branch, query_buf);
374 else if (strcmp(cmd, "s") == 0)
375 status = exec_command_s(scan_state, active_branch);
376 else if (strcmp(cmd, "set") == 0)
377 status = exec_command_set(scan_state, active_branch);
378 else if (strcmp(cmd, "setenv") == 0)
379 status = exec_command_setenv(scan_state, active_branch, cmd);
380 else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
381 status = exec_command_sf(scan_state, active_branch, cmd);
382 else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
383 status = exec_command_sv(scan_state, active_branch, cmd);
384 else if (strcmp(cmd, "t") == 0)
385 status = exec_command_t(scan_state, active_branch);
386 else if (strcmp(cmd, "T") == 0)
387 status = exec_command_T(scan_state, active_branch);
388 else if (strcmp(cmd, "timing") == 0)
389 status = exec_command_timing(scan_state, active_branch);
390 else if (strcmp(cmd, "unset") == 0)
391 status = exec_command_unset(scan_state, active_branch, cmd);
392 else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
393 status = exec_command_write(scan_state, active_branch, cmd,
394 query_buf, previous_buf);
395 else if (strcmp(cmd, "watch") == 0)
396 status = exec_command_watch(scan_state, active_branch,
397 query_buf, previous_buf);
398 else if (strcmp(cmd, "x") == 0)
399 status = exec_command_x(scan_state, active_branch);
400 else if (strcmp(cmd, "z") == 0)
401 status = exec_command_z(scan_state, active_branch);
402 else if (strcmp(cmd, "!") == 0)
403 status = exec_command_shell_escape(scan_state, active_branch);
404 else if (strcmp(cmd, "?") == 0)
405 status = exec_command_slash_command_help(scan_state, active_branch);
406 else
407 status = PSQL_CMD_UNKNOWN;
408
409 /*
410 * All the commands that return PSQL_CMD_SEND want to execute previous_buf
411 * if query_buf is empty. For convenience we implement that here, not in
412 * the individual command subroutines.
413 */
414 if (status == PSQL_CMD_SEND)
415 copy_previous_query(query_buf, previous_buf);
416
417 return status;
418 }
419
420
421 /*
422 * \a -- toggle field alignment
423 *
424 * This makes little sense but we keep it around.
425 */
426 static backslashResult
exec_command_a(PsqlScanState scan_state,bool active_branch)427 exec_command_a(PsqlScanState scan_state, bool active_branch)
428 {
429 bool success = true;
430
431 if (active_branch)
432 {
433 if (pset.popt.topt.format != PRINT_ALIGNED)
434 success = do_pset("format", "aligned", &pset.popt, pset.quiet);
435 else
436 success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
437 }
438
439 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
440 }
441
442 /*
443 * \C -- override table title (formerly change HTML caption)
444 */
445 static backslashResult
exec_command_C(PsqlScanState scan_state,bool active_branch)446 exec_command_C(PsqlScanState scan_state, bool active_branch)
447 {
448 bool success = true;
449
450 if (active_branch)
451 {
452 char *opt = psql_scan_slash_option(scan_state,
453 OT_NORMAL, NULL, true);
454
455 success = do_pset("title", opt, &pset.popt, pset.quiet);
456 free(opt);
457 }
458 else
459 ignore_slash_options(scan_state);
460
461 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
462 }
463
464 /*
465 * \c or \connect -- connect to database using the specified parameters.
466 *
467 * \c [-reuse-previous=BOOL] dbname user host port
468 *
469 * Specifying a parameter as '-' is equivalent to omitting it. Examples:
470 *
471 * \c - - hst Connect to current database on current port of
472 * host "hst" as current user.
473 * \c - usr - prt Connect to current database on port "prt" of current host
474 * as user "usr".
475 * \c dbs Connect to database "dbs" on current port of current host
476 * as current user.
477 */
478 static backslashResult
exec_command_connect(PsqlScanState scan_state,bool active_branch)479 exec_command_connect(PsqlScanState scan_state, bool active_branch)
480 {
481 bool success = true;
482
483 if (active_branch)
484 {
485 static const char prefix[] = "-reuse-previous=";
486 char *opt1,
487 *opt2,
488 *opt3,
489 *opt4;
490 enum trivalue reuse_previous = TRI_DEFAULT;
491
492 opt1 = read_connect_arg(scan_state);
493 if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
494 {
495 bool on_off;
496
497 success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
498 "-reuse-previous",
499 &on_off);
500 if (success)
501 {
502 reuse_previous = on_off ? TRI_YES : TRI_NO;
503 free(opt1);
504 opt1 = read_connect_arg(scan_state);
505 }
506 }
507
508 if (success) /* give up if reuse_previous was invalid */
509 {
510 opt2 = read_connect_arg(scan_state);
511 opt3 = read_connect_arg(scan_state);
512 opt4 = read_connect_arg(scan_state);
513
514 success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
515
516 free(opt2);
517 free(opt3);
518 free(opt4);
519 }
520 free(opt1);
521 }
522 else
523 ignore_slash_options(scan_state);
524
525 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
526 }
527
528 /*
529 * \cd -- change directory
530 */
531 static backslashResult
exec_command_cd(PsqlScanState scan_state,bool active_branch,const char * cmd)532 exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
533 {
534 bool success = true;
535
536 if (active_branch)
537 {
538 char *opt = psql_scan_slash_option(scan_state,
539 OT_NORMAL, NULL, true);
540 char *dir;
541
542 if (opt)
543 dir = opt;
544 else
545 {
546 #ifndef WIN32
547 struct passwd *pw;
548 uid_t user_id = geteuid();
549
550 errno = 0; /* clear errno before call */
551 pw = getpwuid(user_id);
552 if (!pw)
553 {
554 psql_error("could not get home directory for user ID %ld: %s\n",
555 (long) user_id,
556 errno ? strerror(errno) : _("user does not exist"));
557 exit(EXIT_FAILURE);
558 }
559 dir = pw->pw_dir;
560 #else /* WIN32 */
561
562 /*
563 * On Windows, 'cd' without arguments prints the current
564 * directory, so if someone wants to code this here instead...
565 */
566 dir = "/";
567 #endif /* WIN32 */
568 }
569
570 if (chdir(dir) == -1)
571 {
572 psql_error("\\%s: could not change directory to \"%s\": %s\n",
573 cmd, dir, strerror(errno));
574 success = false;
575 }
576
577 if (opt)
578 free(opt);
579 }
580 else
581 ignore_slash_options(scan_state);
582
583 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
584 }
585
586 /*
587 * \conninfo -- display information about the current connection
588 */
589 static backslashResult
exec_command_conninfo(PsqlScanState scan_state,bool active_branch)590 exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
591 {
592 if (active_branch)
593 {
594 char *db = PQdb(pset.db);
595
596 if (db == NULL)
597 printf(_("You are currently not connected to a database.\n"));
598 else
599 {
600 char *host = PQhost(pset.db);
601
602 /* If the host is an absolute path, the connection is via socket */
603 if (is_absolute_path(host))
604 printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
605 db, PQuser(pset.db), host, PQport(pset.db));
606 else
607 printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
608 db, PQuser(pset.db), host, PQport(pset.db));
609 printSSLInfo();
610 }
611 }
612
613 return PSQL_CMD_SKIP_LINE;
614 }
615
616 /*
617 * \copy -- run a COPY command
618 */
619 static backslashResult
exec_command_copy(PsqlScanState scan_state,bool active_branch)620 exec_command_copy(PsqlScanState scan_state, bool active_branch)
621 {
622 bool success = true;
623
624 if (active_branch)
625 {
626 char *opt = psql_scan_slash_option(scan_state,
627 OT_WHOLE_LINE, NULL, false);
628
629 success = do_copy(opt);
630 free(opt);
631 }
632 else
633 ignore_slash_whole_line(scan_state);
634
635 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
636 }
637
638 /*
639 * \copyright -- print copyright notice
640 */
641 static backslashResult
exec_command_copyright(PsqlScanState scan_state,bool active_branch)642 exec_command_copyright(PsqlScanState scan_state, bool active_branch)
643 {
644 if (active_branch)
645 print_copyright();
646
647 return PSQL_CMD_SKIP_LINE;
648 }
649
650 /*
651 * \crosstabview -- execute a query and display results in crosstab
652 */
653 static backslashResult
exec_command_crosstabview(PsqlScanState scan_state,bool active_branch)654 exec_command_crosstabview(PsqlScanState scan_state, bool active_branch)
655 {
656 backslashResult status = PSQL_CMD_SKIP_LINE;
657
658 if (active_branch)
659 {
660 int i;
661
662 for (i = 0; i < lengthof(pset.ctv_args); i++)
663 pset.ctv_args[i] = psql_scan_slash_option(scan_state,
664 OT_NORMAL, NULL, true);
665 pset.crosstab_flag = true;
666 status = PSQL_CMD_SEND;
667 }
668 else
669 ignore_slash_options(scan_state);
670
671 return status;
672 }
673
674 /*
675 * \d* commands
676 */
677 static backslashResult
exec_command_d(PsqlScanState scan_state,bool active_branch,const char * cmd)678 exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
679 {
680 backslashResult status = PSQL_CMD_SKIP_LINE;
681 bool success = true;
682
683 if (active_branch)
684 {
685 char *pattern;
686 bool show_verbose,
687 show_system;
688
689 /* We don't do SQLID reduction on the pattern yet */
690 pattern = psql_scan_slash_option(scan_state,
691 OT_NORMAL, NULL, true);
692
693 show_verbose = strchr(cmd, '+') ? true : false;
694 show_system = strchr(cmd, 'S') ? true : false;
695
696 switch (cmd[1])
697 {
698 case '\0':
699 case '+':
700 case 'S':
701 if (pattern)
702 success = describeTableDetails(pattern, show_verbose, show_system);
703 else
704 /* standard listing of interesting things */
705 success = listTables("tvmsE", NULL, show_verbose, show_system);
706 break;
707 case 'A':
708 success = describeAccessMethods(pattern, show_verbose);
709 break;
710 case 'a':
711 success = describeAggregates(pattern, show_verbose, show_system);
712 break;
713 case 'b':
714 success = describeTablespaces(pattern, show_verbose);
715 break;
716 case 'c':
717 success = listConversions(pattern, show_verbose, show_system);
718 break;
719 case 'C':
720 success = listCasts(pattern, show_verbose);
721 break;
722 case 'd':
723 if (strncmp(cmd, "ddp", 3) == 0)
724 success = listDefaultACLs(pattern);
725 else
726 success = objectDescription(pattern, show_system);
727 break;
728 case 'D':
729 success = listDomains(pattern, show_verbose, show_system);
730 break;
731 case 'f': /* function subsystem */
732 switch (cmd[2])
733 {
734 case '\0':
735 case '+':
736 case 'S':
737 case 'a':
738 case 'n':
739 case 't':
740 case 'w':
741 success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
742 break;
743 default:
744 status = PSQL_CMD_UNKNOWN;
745 break;
746 }
747 break;
748 case 'g':
749 /* no longer distinct from \du */
750 success = describeRoles(pattern, show_verbose, show_system);
751 break;
752 case 'l':
753 success = do_lo_list();
754 break;
755 case 'L':
756 success = listLanguages(pattern, show_verbose, show_system);
757 break;
758 case 'n':
759 success = listSchemas(pattern, show_verbose, show_system);
760 break;
761 case 'o':
762 success = describeOperators(pattern, show_verbose, show_system);
763 break;
764 case 'O':
765 success = listCollations(pattern, show_verbose, show_system);
766 break;
767 case 'p':
768 success = permissionsList(pattern);
769 break;
770 case 'T':
771 success = describeTypes(pattern, show_verbose, show_system);
772 break;
773 case 't':
774 case 'v':
775 case 'm':
776 case 'i':
777 case 's':
778 case 'E':
779 success = listTables(&cmd[1], pattern, show_verbose, show_system);
780 break;
781 case 'r':
782 if (cmd[2] == 'd' && cmd[3] == 's')
783 {
784 char *pattern2 = NULL;
785
786 if (pattern)
787 pattern2 = psql_scan_slash_option(scan_state,
788 OT_NORMAL, NULL, true);
789 success = listDbRoleSettings(pattern, pattern2);
790
791 if (pattern2)
792 free(pattern2);
793 }
794 else
795 status = PSQL_CMD_UNKNOWN;
796 break;
797 case 'R':
798 switch (cmd[2])
799 {
800 case 'p':
801 if (show_verbose)
802 success = describePublications(pattern);
803 else
804 success = listPublications(pattern);
805 break;
806 case 's':
807 success = describeSubscriptions(pattern, show_verbose);
808 break;
809 default:
810 status = PSQL_CMD_UNKNOWN;
811 }
812 break;
813 case 'u':
814 success = describeRoles(pattern, show_verbose, show_system);
815 break;
816 case 'F': /* text search subsystem */
817 switch (cmd[2])
818 {
819 case '\0':
820 case '+':
821 success = listTSConfigs(pattern, show_verbose);
822 break;
823 case 'p':
824 success = listTSParsers(pattern, show_verbose);
825 break;
826 case 'd':
827 success = listTSDictionaries(pattern, show_verbose);
828 break;
829 case 't':
830 success = listTSTemplates(pattern, show_verbose);
831 break;
832 default:
833 status = PSQL_CMD_UNKNOWN;
834 break;
835 }
836 break;
837 case 'e': /* SQL/MED subsystem */
838 switch (cmd[2])
839 {
840 case 's':
841 success = listForeignServers(pattern, show_verbose);
842 break;
843 case 'u':
844 success = listUserMappings(pattern, show_verbose);
845 break;
846 case 'w':
847 success = listForeignDataWrappers(pattern, show_verbose);
848 break;
849 case 't':
850 success = listForeignTables(pattern, show_verbose);
851 break;
852 default:
853 status = PSQL_CMD_UNKNOWN;
854 break;
855 }
856 break;
857 case 'x': /* Extensions */
858 if (show_verbose)
859 success = listExtensionContents(pattern);
860 else
861 success = listExtensions(pattern);
862 break;
863 case 'y': /* Event Triggers */
864 success = listEventTriggers(pattern, show_verbose);
865 break;
866 default:
867 status = PSQL_CMD_UNKNOWN;
868 }
869
870 if (pattern)
871 free(pattern);
872 }
873 else
874 ignore_slash_options(scan_state);
875
876 if (!success)
877 status = PSQL_CMD_ERROR;
878
879 return status;
880 }
881
882 /*
883 * \e or \edit -- edit the current query buffer, or edit a file and
884 * make it the query buffer
885 */
886 static backslashResult
exec_command_edit(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)887 exec_command_edit(PsqlScanState scan_state, bool active_branch,
888 PQExpBuffer query_buf, PQExpBuffer previous_buf)
889 {
890 backslashResult status = PSQL_CMD_SKIP_LINE;
891
892 if (active_branch)
893 {
894 if (!query_buf)
895 {
896 psql_error("no query buffer\n");
897 status = PSQL_CMD_ERROR;
898 }
899 else
900 {
901 char *fname;
902 char *ln = NULL;
903 int lineno = -1;
904
905 fname = psql_scan_slash_option(scan_state,
906 OT_NORMAL, NULL, true);
907 if (fname)
908 {
909 /* try to get separate lineno arg */
910 ln = psql_scan_slash_option(scan_state,
911 OT_NORMAL, NULL, true);
912 if (ln == NULL)
913 {
914 /* only one arg; maybe it is lineno not fname */
915 if (fname[0] &&
916 strspn(fname, "0123456789") == strlen(fname))
917 {
918 /* all digits, so assume it is lineno */
919 ln = fname;
920 fname = NULL;
921 }
922 }
923 }
924 if (ln)
925 {
926 lineno = atoi(ln);
927 if (lineno < 1)
928 {
929 psql_error("invalid line number: %s\n", ln);
930 status = PSQL_CMD_ERROR;
931 }
932 }
933 if (status != PSQL_CMD_ERROR)
934 {
935 expand_tilde(&fname);
936 if (fname)
937 canonicalize_path(fname);
938
939 /* If query_buf is empty, recall previous query for editing */
940 copy_previous_query(query_buf, previous_buf);
941
942 if (do_edit(fname, query_buf, lineno, NULL))
943 status = PSQL_CMD_NEWEDIT;
944 else
945 status = PSQL_CMD_ERROR;
946 }
947 if (fname)
948 free(fname);
949 if (ln)
950 free(ln);
951 }
952 }
953 else
954 ignore_slash_options(scan_state);
955
956 return status;
957 }
958
959 /*
960 * \ef -- edit the named function, or present a blank CREATE FUNCTION
961 * template if no argument is given
962 */
963 static backslashResult
exec_command_ef(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf)964 exec_command_ef(PsqlScanState scan_state, bool active_branch,
965 PQExpBuffer query_buf)
966 {
967 backslashResult status = PSQL_CMD_SKIP_LINE;
968
969 if (active_branch)
970 {
971 char *func = psql_scan_slash_option(scan_state,
972 OT_WHOLE_LINE, NULL, true);
973 int lineno = -1;
974
975 if (pset.sversion < 80400)
976 {
977 char sverbuf[32];
978
979 psql_error("The server (version %s) does not support editing function source.\n",
980 formatPGVersionNumber(pset.sversion, false,
981 sverbuf, sizeof(sverbuf)));
982 status = PSQL_CMD_ERROR;
983 }
984 else if (!query_buf)
985 {
986 psql_error("no query buffer\n");
987 status = PSQL_CMD_ERROR;
988 }
989 else
990 {
991 Oid foid = InvalidOid;
992
993 lineno = strip_lineno_from_objdesc(func);
994 if (lineno == 0)
995 {
996 /* error already reported */
997 status = PSQL_CMD_ERROR;
998 }
999 else if (!func)
1000 {
1001 /* set up an empty command to fill in */
1002 printfPQExpBuffer(query_buf,
1003 "CREATE FUNCTION ( )\n"
1004 " RETURNS \n"
1005 " LANGUAGE \n"
1006 " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
1007 "AS $function$\n"
1008 "\n$function$\n");
1009 }
1010 else if (!lookup_object_oid(EditableFunction, func, &foid))
1011 {
1012 /* error already reported */
1013 status = PSQL_CMD_ERROR;
1014 }
1015 else if (!get_create_object_cmd(EditableFunction, foid, query_buf))
1016 {
1017 /* error already reported */
1018 status = PSQL_CMD_ERROR;
1019 }
1020 else if (lineno > 0)
1021 {
1022 /*
1023 * lineno "1" should correspond to the first line of the
1024 * function body. We expect that pg_get_functiondef() will
1025 * emit that on a line beginning with "AS ", and that there
1026 * can be no such line before the real start of the function
1027 * body. Increment lineno by the number of lines before that
1028 * line, so that it becomes relative to the first line of the
1029 * function definition.
1030 */
1031 const char *lines = query_buf->data;
1032
1033 while (*lines != '\0')
1034 {
1035 if (strncmp(lines, "AS ", 3) == 0)
1036 break;
1037 lineno++;
1038 /* find start of next line */
1039 lines = strchr(lines, '\n');
1040 if (!lines)
1041 break;
1042 lines++;
1043 }
1044 }
1045 }
1046
1047 if (status != PSQL_CMD_ERROR)
1048 {
1049 bool edited = false;
1050
1051 if (!do_edit(NULL, query_buf, lineno, &edited))
1052 status = PSQL_CMD_ERROR;
1053 else if (!edited)
1054 puts(_("No changes"));
1055 else
1056 status = PSQL_CMD_NEWEDIT;
1057 }
1058
1059 if (func)
1060 free(func);
1061 }
1062 else
1063 ignore_slash_whole_line(scan_state);
1064
1065 return status;
1066 }
1067
1068 /*
1069 * \ev -- edit the named view, or present a blank CREATE VIEW
1070 * template if no argument is given
1071 */
1072 static backslashResult
exec_command_ev(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf)1073 exec_command_ev(PsqlScanState scan_state, bool active_branch,
1074 PQExpBuffer query_buf)
1075 {
1076 backslashResult status = PSQL_CMD_SKIP_LINE;
1077
1078 if (active_branch)
1079 {
1080 char *view = psql_scan_slash_option(scan_state,
1081 OT_WHOLE_LINE, NULL, true);
1082 int lineno = -1;
1083
1084 if (pset.sversion < 70400)
1085 {
1086 char sverbuf[32];
1087
1088 psql_error("The server (version %s) does not support editing view definitions.\n",
1089 formatPGVersionNumber(pset.sversion, false,
1090 sverbuf, sizeof(sverbuf)));
1091 status = PSQL_CMD_ERROR;
1092 }
1093 else if (!query_buf)
1094 {
1095 psql_error("no query buffer\n");
1096 status = PSQL_CMD_ERROR;
1097 }
1098 else
1099 {
1100 Oid view_oid = InvalidOid;
1101
1102 lineno = strip_lineno_from_objdesc(view);
1103 if (lineno == 0)
1104 {
1105 /* error already reported */
1106 status = PSQL_CMD_ERROR;
1107 }
1108 else if (!view)
1109 {
1110 /* set up an empty command to fill in */
1111 printfPQExpBuffer(query_buf,
1112 "CREATE VIEW AS\n"
1113 " SELECT \n"
1114 " -- something...\n");
1115 }
1116 else if (!lookup_object_oid(EditableView, view, &view_oid))
1117 {
1118 /* error already reported */
1119 status = PSQL_CMD_ERROR;
1120 }
1121 else if (!get_create_object_cmd(EditableView, view_oid, query_buf))
1122 {
1123 /* error already reported */
1124 status = PSQL_CMD_ERROR;
1125 }
1126 }
1127
1128 if (status != PSQL_CMD_ERROR)
1129 {
1130 bool edited = false;
1131
1132 if (!do_edit(NULL, query_buf, lineno, &edited))
1133 status = PSQL_CMD_ERROR;
1134 else if (!edited)
1135 puts(_("No changes"));
1136 else
1137 status = PSQL_CMD_NEWEDIT;
1138 }
1139
1140 if (view)
1141 free(view);
1142 }
1143 else
1144 ignore_slash_whole_line(scan_state);
1145
1146 return status;
1147 }
1148
1149 /*
1150 * \echo and \qecho -- echo arguments to stdout or query output
1151 */
1152 static backslashResult
exec_command_echo(PsqlScanState scan_state,bool active_branch,const char * cmd)1153 exec_command_echo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1154 {
1155 if (active_branch)
1156 {
1157 char *value;
1158 char quoted;
1159 bool no_newline = false;
1160 bool first = true;
1161 FILE *fout;
1162
1163 if (strcmp(cmd, "qecho") == 0)
1164 fout = pset.queryFout;
1165 else
1166 fout = stdout;
1167
1168 while ((value = psql_scan_slash_option(scan_state,
1169 OT_NORMAL, "ed, false)))
1170 {
1171 if (!quoted && strcmp(value, "-n") == 0)
1172 no_newline = true;
1173 else
1174 {
1175 if (first)
1176 first = false;
1177 else
1178 fputc(' ', fout);
1179 fputs(value, fout);
1180 }
1181 free(value);
1182 }
1183 if (!no_newline)
1184 fputs("\n", fout);
1185 }
1186 else
1187 ignore_slash_options(scan_state);
1188
1189 return PSQL_CMD_SKIP_LINE;
1190 }
1191
1192 /*
1193 * \encoding -- set/show client side encoding
1194 */
1195 static backslashResult
exec_command_encoding(PsqlScanState scan_state,bool active_branch)1196 exec_command_encoding(PsqlScanState scan_state, bool active_branch)
1197 {
1198 if (active_branch)
1199 {
1200 char *encoding = psql_scan_slash_option(scan_state,
1201 OT_NORMAL, NULL, false);
1202
1203 if (!encoding)
1204 {
1205 /* show encoding */
1206 puts(pg_encoding_to_char(pset.encoding));
1207 }
1208 else
1209 {
1210 /* set encoding */
1211 if (PQsetClientEncoding(pset.db, encoding) == -1)
1212 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
1213 else
1214 {
1215 /* save encoding info into psql internal data */
1216 pset.encoding = PQclientEncoding(pset.db);
1217 pset.popt.topt.encoding = pset.encoding;
1218 SetVariable(pset.vars, "ENCODING",
1219 pg_encoding_to_char(pset.encoding));
1220 }
1221 free(encoding);
1222 }
1223 }
1224 else
1225 ignore_slash_options(scan_state);
1226
1227 return PSQL_CMD_SKIP_LINE;
1228 }
1229
1230 /*
1231 * \errverbose -- display verbose message from last failed query
1232 */
1233 static backslashResult
exec_command_errverbose(PsqlScanState scan_state,bool active_branch)1234 exec_command_errverbose(PsqlScanState scan_state, bool active_branch)
1235 {
1236 if (active_branch)
1237 {
1238 if (pset.last_error_result)
1239 {
1240 char *msg;
1241
1242 msg = PQresultVerboseErrorMessage(pset.last_error_result,
1243 PQERRORS_VERBOSE,
1244 PQSHOW_CONTEXT_ALWAYS);
1245 if (msg)
1246 {
1247 psql_error("%s", msg);
1248 PQfreemem(msg);
1249 }
1250 else
1251 puts(_("out of memory"));
1252 }
1253 else
1254 puts(_("There is no previous error."));
1255 }
1256
1257 return PSQL_CMD_SKIP_LINE;
1258 }
1259
1260 /*
1261 * \f -- change field separator
1262 */
1263 static backslashResult
exec_command_f(PsqlScanState scan_state,bool active_branch)1264 exec_command_f(PsqlScanState scan_state, bool active_branch)
1265 {
1266 bool success = true;
1267
1268 if (active_branch)
1269 {
1270 char *fname = psql_scan_slash_option(scan_state,
1271 OT_NORMAL, NULL, false);
1272
1273 success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
1274 free(fname);
1275 }
1276 else
1277 ignore_slash_options(scan_state);
1278
1279 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1280 }
1281
1282 /*
1283 * \g [filename] -- send query, optionally with output to file/pipe
1284 * \gx [filename] -- same as \g, with expanded mode forced
1285 */
1286 static backslashResult
exec_command_g(PsqlScanState scan_state,bool active_branch,const char * cmd)1287 exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
1288 {
1289 backslashResult status = PSQL_CMD_SKIP_LINE;
1290
1291 if (active_branch)
1292 {
1293 char *fname = psql_scan_slash_option(scan_state,
1294 OT_FILEPIPE, NULL, false);
1295
1296 if (!fname)
1297 pset.gfname = NULL;
1298 else
1299 {
1300 expand_tilde(&fname);
1301 pset.gfname = pg_strdup(fname);
1302 }
1303 free(fname);
1304 if (strcmp(cmd, "gx") == 0)
1305 pset.g_expanded = true;
1306 status = PSQL_CMD_SEND;
1307 }
1308 else
1309 ignore_slash_filepipe(scan_state);
1310
1311 return status;
1312 }
1313
1314 /*
1315 * \gexec -- send query and execute each field of result
1316 */
1317 static backslashResult
exec_command_gexec(PsqlScanState scan_state,bool active_branch)1318 exec_command_gexec(PsqlScanState scan_state, bool active_branch)
1319 {
1320 backslashResult status = PSQL_CMD_SKIP_LINE;
1321
1322 if (active_branch)
1323 {
1324 pset.gexec_flag = true;
1325 status = PSQL_CMD_SEND;
1326 }
1327
1328 return status;
1329 }
1330
1331 /*
1332 * \gset [prefix] -- send query and store result into variables
1333 */
1334 static backslashResult
exec_command_gset(PsqlScanState scan_state,bool active_branch)1335 exec_command_gset(PsqlScanState scan_state, bool active_branch)
1336 {
1337 backslashResult status = PSQL_CMD_SKIP_LINE;
1338
1339 if (active_branch)
1340 {
1341 char *prefix = psql_scan_slash_option(scan_state,
1342 OT_NORMAL, NULL, false);
1343
1344 if (prefix)
1345 pset.gset_prefix = prefix;
1346 else
1347 {
1348 /* we must set a non-NULL prefix to trigger storing */
1349 pset.gset_prefix = pg_strdup("");
1350 }
1351 /* gset_prefix is freed later */
1352 status = PSQL_CMD_SEND;
1353 }
1354 else
1355 ignore_slash_options(scan_state);
1356
1357 return status;
1358 }
1359
1360 /*
1361 * \help [topic] -- print help about SQL commands
1362 */
1363 static backslashResult
exec_command_help(PsqlScanState scan_state,bool active_branch)1364 exec_command_help(PsqlScanState scan_state, bool active_branch)
1365 {
1366 if (active_branch)
1367 {
1368 char *opt = psql_scan_slash_option(scan_state,
1369 OT_WHOLE_LINE, NULL, false);
1370 size_t len;
1371
1372 /* strip any trailing spaces and semicolons */
1373 if (opt)
1374 {
1375 len = strlen(opt);
1376 while (len > 0 &&
1377 (isspace((unsigned char) opt[len - 1])
1378 || opt[len - 1] == ';'))
1379 opt[--len] = '\0';
1380 }
1381
1382 helpSQL(opt, pset.popt.topt.pager);
1383 free(opt);
1384 }
1385 else
1386 ignore_slash_whole_line(scan_state);
1387
1388 return PSQL_CMD_SKIP_LINE;
1389 }
1390
1391 /*
1392 * \H and \html -- toggle HTML formatting
1393 */
1394 static backslashResult
exec_command_html(PsqlScanState scan_state,bool active_branch)1395 exec_command_html(PsqlScanState scan_state, bool active_branch)
1396 {
1397 bool success = true;
1398
1399 if (active_branch)
1400 {
1401 if (pset.popt.topt.format != PRINT_HTML)
1402 success = do_pset("format", "html", &pset.popt, pset.quiet);
1403 else
1404 success = do_pset("format", "aligned", &pset.popt, pset.quiet);
1405 }
1406
1407 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1408 }
1409
1410 /*
1411 * \i and \ir -- include a file
1412 */
1413 static backslashResult
exec_command_include(PsqlScanState scan_state,bool active_branch,const char * cmd)1414 exec_command_include(PsqlScanState scan_state, bool active_branch, const char *cmd)
1415 {
1416 bool success = true;
1417
1418 if (active_branch)
1419 {
1420 char *fname = psql_scan_slash_option(scan_state,
1421 OT_NORMAL, NULL, true);
1422
1423 if (!fname)
1424 {
1425 psql_error("\\%s: missing required argument\n", cmd);
1426 success = false;
1427 }
1428 else
1429 {
1430 bool include_relative;
1431
1432 include_relative = (strcmp(cmd, "ir") == 0
1433 || strcmp(cmd, "include_relative") == 0);
1434 expand_tilde(&fname);
1435 success = (process_file(fname, include_relative) == EXIT_SUCCESS);
1436 free(fname);
1437 }
1438 }
1439 else
1440 ignore_slash_options(scan_state);
1441
1442 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1443 }
1444
1445 /*
1446 * \if <expr> -- beginning of an \if..\endif block
1447 *
1448 * <expr> is parsed as a boolean expression. Invalid expressions will emit a
1449 * warning and be treated as false. Statements that follow a false expression
1450 * will be parsed but ignored. Note that in the case where an \if statement
1451 * is itself within an inactive section of a block, then the entire inner
1452 * \if..\endif block will be parsed but ignored.
1453 */
1454 static backslashResult
exec_command_if(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1455 exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
1456 PQExpBuffer query_buf)
1457 {
1458 if (conditional_active(cstack))
1459 {
1460 /*
1461 * First, push a new active stack entry; this ensures that the lexer
1462 * will perform variable substitution and backtick evaluation while
1463 * scanning the expression. (That should happen anyway, since we know
1464 * we're in an active outer branch, but let's be sure.)
1465 */
1466 conditional_stack_push(cstack, IFSTATE_TRUE);
1467
1468 /* Remember current query state in case we need to restore later */
1469 save_query_text_state(scan_state, cstack, query_buf);
1470
1471 /*
1472 * Evaluate the expression; if it's false, change to inactive state.
1473 */
1474 if (!is_true_boolean_expression(scan_state, "\\if expression"))
1475 conditional_stack_poke(cstack, IFSTATE_FALSE);
1476 }
1477 else
1478 {
1479 /*
1480 * We're within an inactive outer branch, so this entire \if block
1481 * will be ignored. We don't want to evaluate the expression, so push
1482 * the "ignored" stack state before scanning it.
1483 */
1484 conditional_stack_push(cstack, IFSTATE_IGNORED);
1485
1486 /* Remember current query state in case we need to restore later */
1487 save_query_text_state(scan_state, cstack, query_buf);
1488
1489 ignore_boolean_expression(scan_state);
1490 }
1491
1492 return PSQL_CMD_SKIP_LINE;
1493 }
1494
1495 /*
1496 * \elif <expr> -- alternative branch in an \if..\endif block
1497 *
1498 * <expr> is evaluated the same as in \if <expr>.
1499 */
1500 static backslashResult
exec_command_elif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1501 exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
1502 PQExpBuffer query_buf)
1503 {
1504 bool success = true;
1505
1506 switch (conditional_stack_peek(cstack))
1507 {
1508 case IFSTATE_TRUE:
1509
1510 /*
1511 * Just finished active branch of this \if block. Update saved
1512 * state so we will keep whatever data was put in query_buf by the
1513 * active branch.
1514 */
1515 save_query_text_state(scan_state, cstack, query_buf);
1516
1517 /*
1518 * Discard \elif expression and ignore the rest until \endif.
1519 * Switch state before reading expression to ensure proper lexer
1520 * behavior.
1521 */
1522 conditional_stack_poke(cstack, IFSTATE_IGNORED);
1523 ignore_boolean_expression(scan_state);
1524 break;
1525 case IFSTATE_FALSE:
1526
1527 /*
1528 * Discard any query text added by the just-skipped branch.
1529 */
1530 discard_query_text(scan_state, cstack, query_buf);
1531
1532 /*
1533 * Have not yet found a true expression in this \if block, so this
1534 * might be the first. We have to change state before examining
1535 * the expression, or the lexer won't do the right thing.
1536 */
1537 conditional_stack_poke(cstack, IFSTATE_TRUE);
1538 if (!is_true_boolean_expression(scan_state, "\\elif expression"))
1539 conditional_stack_poke(cstack, IFSTATE_FALSE);
1540 break;
1541 case IFSTATE_IGNORED:
1542
1543 /*
1544 * Discard any query text added by the just-skipped branch.
1545 */
1546 discard_query_text(scan_state, cstack, query_buf);
1547
1548 /*
1549 * Skip expression and move on. Either the \if block already had
1550 * an active section, or whole block is being skipped.
1551 */
1552 ignore_boolean_expression(scan_state);
1553 break;
1554 case IFSTATE_ELSE_TRUE:
1555 case IFSTATE_ELSE_FALSE:
1556 psql_error("\\elif: cannot occur after \\else\n");
1557 success = false;
1558 break;
1559 case IFSTATE_NONE:
1560 /* no \if to elif from */
1561 psql_error("\\elif: no matching \\if\n");
1562 success = false;
1563 break;
1564 }
1565
1566 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1567 }
1568
1569 /*
1570 * \else -- final alternative in an \if..\endif block
1571 *
1572 * Statements within an \else branch will only be executed if
1573 * all previous \if and \elif expressions evaluated to false
1574 * and the block was not itself being ignored.
1575 */
1576 static backslashResult
exec_command_else(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1577 exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
1578 PQExpBuffer query_buf)
1579 {
1580 bool success = true;
1581
1582 switch (conditional_stack_peek(cstack))
1583 {
1584 case IFSTATE_TRUE:
1585
1586 /*
1587 * Just finished active branch of this \if block. Update saved
1588 * state so we will keep whatever data was put in query_buf by the
1589 * active branch.
1590 */
1591 save_query_text_state(scan_state, cstack, query_buf);
1592
1593 /* Now skip the \else branch */
1594 conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1595 break;
1596 case IFSTATE_FALSE:
1597
1598 /*
1599 * Discard any query text added by the just-skipped branch.
1600 */
1601 discard_query_text(scan_state, cstack, query_buf);
1602
1603 /*
1604 * We've not found any true \if or \elif expression, so execute
1605 * the \else branch.
1606 */
1607 conditional_stack_poke(cstack, IFSTATE_ELSE_TRUE);
1608 break;
1609 case IFSTATE_IGNORED:
1610
1611 /*
1612 * Discard any query text added by the just-skipped branch.
1613 */
1614 discard_query_text(scan_state, cstack, query_buf);
1615
1616 /*
1617 * Either we previously processed the active branch of this \if,
1618 * or the whole \if block is being skipped. Either way, skip the
1619 * \else branch.
1620 */
1621 conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1622 break;
1623 case IFSTATE_ELSE_TRUE:
1624 case IFSTATE_ELSE_FALSE:
1625 psql_error("\\else: cannot occur after \\else\n");
1626 success = false;
1627 break;
1628 case IFSTATE_NONE:
1629 /* no \if to else from */
1630 psql_error("\\else: no matching \\if\n");
1631 success = false;
1632 break;
1633 }
1634
1635 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1636 }
1637
1638 /*
1639 * \endif -- ends an \if...\endif block
1640 */
1641 static backslashResult
exec_command_endif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1642 exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
1643 PQExpBuffer query_buf)
1644 {
1645 bool success = true;
1646
1647 switch (conditional_stack_peek(cstack))
1648 {
1649 case IFSTATE_TRUE:
1650 case IFSTATE_ELSE_TRUE:
1651 /* Close the \if block, keeping the query text */
1652 success = conditional_stack_pop(cstack);
1653 Assert(success);
1654 break;
1655 case IFSTATE_FALSE:
1656 case IFSTATE_IGNORED:
1657 case IFSTATE_ELSE_FALSE:
1658
1659 /*
1660 * Discard any query text added by the just-skipped branch.
1661 */
1662 discard_query_text(scan_state, cstack, query_buf);
1663
1664 /* Close the \if block */
1665 success = conditional_stack_pop(cstack);
1666 Assert(success);
1667 break;
1668 case IFSTATE_NONE:
1669 /* no \if to end */
1670 psql_error("\\endif: no matching \\if\n");
1671 success = false;
1672 break;
1673 }
1674
1675 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1676 }
1677
1678 /*
1679 * \l -- list databases
1680 */
1681 static backslashResult
exec_command_list(PsqlScanState scan_state,bool active_branch,const char * cmd)1682 exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
1683 {
1684 bool success = true;
1685
1686 if (active_branch)
1687 {
1688 char *pattern;
1689 bool show_verbose;
1690
1691 pattern = psql_scan_slash_option(scan_state,
1692 OT_NORMAL, NULL, true);
1693
1694 show_verbose = strchr(cmd, '+') ? true : false;
1695
1696 success = listAllDbs(pattern, show_verbose);
1697
1698 if (pattern)
1699 free(pattern);
1700 }
1701 else
1702 ignore_slash_options(scan_state);
1703
1704 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1705 }
1706
1707 /*
1708 * \lo_* -- large object operations
1709 */
1710 static backslashResult
exec_command_lo(PsqlScanState scan_state,bool active_branch,const char * cmd)1711 exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1712 {
1713 backslashResult status = PSQL_CMD_SKIP_LINE;
1714 bool success = true;
1715
1716 if (active_branch)
1717 {
1718 char *opt1,
1719 *opt2;
1720
1721 opt1 = psql_scan_slash_option(scan_state,
1722 OT_NORMAL, NULL, true);
1723 opt2 = psql_scan_slash_option(scan_state,
1724 OT_NORMAL, NULL, true);
1725
1726 if (strcmp(cmd + 3, "export") == 0)
1727 {
1728 if (!opt2)
1729 {
1730 psql_error("\\%s: missing required argument\n", cmd);
1731 success = false;
1732 }
1733 else
1734 {
1735 expand_tilde(&opt2);
1736 success = do_lo_export(opt1, opt2);
1737 }
1738 }
1739
1740 else if (strcmp(cmd + 3, "import") == 0)
1741 {
1742 if (!opt1)
1743 {
1744 psql_error("\\%s: missing required argument\n", cmd);
1745 success = false;
1746 }
1747 else
1748 {
1749 expand_tilde(&opt1);
1750 success = do_lo_import(opt1, opt2);
1751 }
1752 }
1753
1754 else if (strcmp(cmd + 3, "list") == 0)
1755 success = do_lo_list();
1756
1757 else if (strcmp(cmd + 3, "unlink") == 0)
1758 {
1759 if (!opt1)
1760 {
1761 psql_error("\\%s: missing required argument\n", cmd);
1762 success = false;
1763 }
1764 else
1765 success = do_lo_unlink(opt1);
1766 }
1767
1768 else
1769 status = PSQL_CMD_UNKNOWN;
1770
1771 free(opt1);
1772 free(opt2);
1773 }
1774 else
1775 ignore_slash_options(scan_state);
1776
1777 if (!success)
1778 status = PSQL_CMD_ERROR;
1779
1780 return status;
1781 }
1782
1783 /*
1784 * \o -- set query output
1785 */
1786 static backslashResult
exec_command_out(PsqlScanState scan_state,bool active_branch)1787 exec_command_out(PsqlScanState scan_state, bool active_branch)
1788 {
1789 bool success = true;
1790
1791 if (active_branch)
1792 {
1793 char *fname = psql_scan_slash_option(scan_state,
1794 OT_FILEPIPE, NULL, true);
1795
1796 expand_tilde(&fname);
1797 success = setQFout(fname);
1798 free(fname);
1799 }
1800 else
1801 ignore_slash_filepipe(scan_state);
1802
1803 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1804 }
1805
1806 /*
1807 * \p -- print the current query buffer
1808 */
1809 static backslashResult
exec_command_print(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)1810 exec_command_print(PsqlScanState scan_state, bool active_branch,
1811 PQExpBuffer query_buf, PQExpBuffer previous_buf)
1812 {
1813 if (active_branch)
1814 {
1815 /*
1816 * We want to print the same thing \g would execute, but not to change
1817 * the query buffer state; so we can't use copy_previous_query().
1818 * Also, beware of possibility that buffer pointers are NULL.
1819 */
1820 if (query_buf && query_buf->len > 0)
1821 puts(query_buf->data);
1822 else if (previous_buf && previous_buf->len > 0)
1823 puts(previous_buf->data);
1824 else if (!pset.quiet)
1825 puts(_("Query buffer is empty."));
1826 fflush(stdout);
1827 }
1828
1829 return PSQL_CMD_SKIP_LINE;
1830 }
1831
1832 /*
1833 * \password -- set user password
1834 */
1835 static backslashResult
exec_command_password(PsqlScanState scan_state,bool active_branch)1836 exec_command_password(PsqlScanState scan_state, bool active_branch)
1837 {
1838 bool success = true;
1839
1840 if (active_branch)
1841 {
1842 char *opt0 = psql_scan_slash_option(scan_state,
1843 OT_SQLID, NULL, true);
1844 char pw1[100];
1845 char pw2[100];
1846
1847 simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
1848 simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
1849
1850 if (strcmp(pw1, pw2) != 0)
1851 {
1852 psql_error("Passwords didn't match.\n");
1853 success = false;
1854 }
1855 else
1856 {
1857 char *user;
1858 char *encrypted_password;
1859
1860 if (opt0)
1861 user = opt0;
1862 else
1863 user = PQuser(pset.db);
1864
1865 encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL);
1866
1867 if (!encrypted_password)
1868 {
1869 psql_error("%s", PQerrorMessage(pset.db));
1870 success = false;
1871 }
1872 else
1873 {
1874 PQExpBufferData buf;
1875 PGresult *res;
1876
1877 initPQExpBuffer(&buf);
1878 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
1879 fmtId(user));
1880 appendStringLiteralConn(&buf, encrypted_password, pset.db);
1881 res = PSQLexec(buf.data);
1882 termPQExpBuffer(&buf);
1883 if (!res)
1884 success = false;
1885 else
1886 PQclear(res);
1887 PQfreemem(encrypted_password);
1888 }
1889 }
1890
1891 if (opt0)
1892 free(opt0);
1893 }
1894 else
1895 ignore_slash_options(scan_state);
1896
1897 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1898 }
1899
1900 /*
1901 * \prompt -- prompt and set variable
1902 */
1903 static backslashResult
exec_command_prompt(PsqlScanState scan_state,bool active_branch,const char * cmd)1904 exec_command_prompt(PsqlScanState scan_state, bool active_branch,
1905 const char *cmd)
1906 {
1907 bool success = true;
1908
1909 if (active_branch)
1910 {
1911 char *opt,
1912 *prompt_text = NULL;
1913 char *arg1,
1914 *arg2;
1915
1916 arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1917 arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1918
1919 if (!arg1)
1920 {
1921 psql_error("\\%s: missing required argument\n", cmd);
1922 success = false;
1923 }
1924 else
1925 {
1926 char *result;
1927
1928 if (arg2)
1929 {
1930 prompt_text = arg1;
1931 opt = arg2;
1932 }
1933 else
1934 opt = arg1;
1935
1936 if (!pset.inputfile)
1937 {
1938 result = (char *) pg_malloc(4096);
1939 simple_prompt(prompt_text, result, 4096, true);
1940 }
1941 else
1942 {
1943 if (prompt_text)
1944 {
1945 fputs(prompt_text, stdout);
1946 fflush(stdout);
1947 }
1948 result = gets_fromFile(stdin);
1949 if (!result)
1950 {
1951 psql_error("\\%s: could not read value for variable\n",
1952 cmd);
1953 success = false;
1954 }
1955 }
1956
1957 if (result &&
1958 !SetVariable(pset.vars, opt, result))
1959 success = false;
1960
1961 if (result)
1962 free(result);
1963 if (prompt_text)
1964 free(prompt_text);
1965 free(opt);
1966 }
1967 }
1968 else
1969 ignore_slash_options(scan_state);
1970
1971 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1972 }
1973
1974 /*
1975 * \pset -- set printing parameters
1976 */
1977 static backslashResult
exec_command_pset(PsqlScanState scan_state,bool active_branch)1978 exec_command_pset(PsqlScanState scan_state, bool active_branch)
1979 {
1980 bool success = true;
1981
1982 if (active_branch)
1983 {
1984 char *opt0 = psql_scan_slash_option(scan_state,
1985 OT_NORMAL, NULL, false);
1986 char *opt1 = psql_scan_slash_option(scan_state,
1987 OT_NORMAL, NULL, false);
1988
1989 if (!opt0)
1990 {
1991 /* list all variables */
1992
1993 int i;
1994 static const char *const my_list[] = {
1995 "border", "columns", "expanded", "fieldsep", "fieldsep_zero",
1996 "footer", "format", "linestyle", "null",
1997 "numericlocale", "pager", "pager_min_lines",
1998 "recordsep", "recordsep_zero",
1999 "tableattr", "title", "tuples_only",
2000 "unicode_border_linestyle",
2001 "unicode_column_linestyle",
2002 "unicode_header_linestyle",
2003 NULL
2004 };
2005
2006 for (i = 0; my_list[i] != NULL; i++)
2007 {
2008 char *val = pset_value_string(my_list[i], &pset.popt);
2009
2010 printf("%-24s %s\n", my_list[i], val);
2011 free(val);
2012 }
2013
2014 success = true;
2015 }
2016 else
2017 success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
2018
2019 free(opt0);
2020 free(opt1);
2021 }
2022 else
2023 ignore_slash_options(scan_state);
2024
2025 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2026 }
2027
2028 /*
2029 * \q or \quit -- exit psql
2030 */
2031 static backslashResult
exec_command_quit(PsqlScanState scan_state,bool active_branch)2032 exec_command_quit(PsqlScanState scan_state, bool active_branch)
2033 {
2034 backslashResult status = PSQL_CMD_SKIP_LINE;
2035
2036 if (active_branch)
2037 status = PSQL_CMD_TERMINATE;
2038
2039 return status;
2040 }
2041
2042 /*
2043 * \r -- reset (clear) the query buffer
2044 */
2045 static backslashResult
exec_command_reset(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf)2046 exec_command_reset(PsqlScanState scan_state, bool active_branch,
2047 PQExpBuffer query_buf)
2048 {
2049 if (active_branch)
2050 {
2051 resetPQExpBuffer(query_buf);
2052 psql_scan_reset(scan_state);
2053 if (!pset.quiet)
2054 puts(_("Query buffer reset (cleared)."));
2055 }
2056
2057 return PSQL_CMD_SKIP_LINE;
2058 }
2059
2060 /*
2061 * \s -- save history in a file or show it on the screen
2062 */
2063 static backslashResult
exec_command_s(PsqlScanState scan_state,bool active_branch)2064 exec_command_s(PsqlScanState scan_state, bool active_branch)
2065 {
2066 bool success = true;
2067
2068 if (active_branch)
2069 {
2070 char *fname = psql_scan_slash_option(scan_state,
2071 OT_NORMAL, NULL, true);
2072
2073 expand_tilde(&fname);
2074 success = printHistory(fname, pset.popt.topt.pager);
2075 if (success && !pset.quiet && fname)
2076 printf(_("Wrote history to file \"%s\".\n"), fname);
2077 if (!fname)
2078 putchar('\n');
2079 free(fname);
2080 }
2081 else
2082 ignore_slash_options(scan_state);
2083
2084 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2085 }
2086
2087 /*
2088 * \set -- set variable
2089 */
2090 static backslashResult
exec_command_set(PsqlScanState scan_state,bool active_branch)2091 exec_command_set(PsqlScanState scan_state, bool active_branch)
2092 {
2093 bool success = true;
2094
2095 if (active_branch)
2096 {
2097 char *opt0 = psql_scan_slash_option(scan_state,
2098 OT_NORMAL, NULL, false);
2099
2100 if (!opt0)
2101 {
2102 /* list all variables */
2103 PrintVariables(pset.vars);
2104 success = true;
2105 }
2106 else
2107 {
2108 /*
2109 * Set variable to the concatenation of the arguments.
2110 */
2111 char *newval;
2112 char *opt;
2113
2114 opt = psql_scan_slash_option(scan_state,
2115 OT_NORMAL, NULL, false);
2116 newval = pg_strdup(opt ? opt : "");
2117 free(opt);
2118
2119 while ((opt = psql_scan_slash_option(scan_state,
2120 OT_NORMAL, NULL, false)))
2121 {
2122 newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
2123 strcat(newval, opt);
2124 free(opt);
2125 }
2126
2127 if (!SetVariable(pset.vars, opt0, newval))
2128 success = false;
2129
2130 free(newval);
2131 }
2132 free(opt0);
2133 }
2134 else
2135 ignore_slash_options(scan_state);
2136
2137 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2138 }
2139
2140 /*
2141 * \setenv -- set environment variable
2142 */
2143 static backslashResult
exec_command_setenv(PsqlScanState scan_state,bool active_branch,const char * cmd)2144 exec_command_setenv(PsqlScanState scan_state, bool active_branch,
2145 const char *cmd)
2146 {
2147 bool success = true;
2148
2149 if (active_branch)
2150 {
2151 char *envvar = psql_scan_slash_option(scan_state,
2152 OT_NORMAL, NULL, false);
2153 char *envval = psql_scan_slash_option(scan_state,
2154 OT_NORMAL, NULL, false);
2155
2156 if (!envvar)
2157 {
2158 psql_error("\\%s: missing required argument\n", cmd);
2159 success = false;
2160 }
2161 else if (strchr(envvar, '=') != NULL)
2162 {
2163 psql_error("\\%s: environment variable name must not contain \"=\"\n",
2164 cmd);
2165 success = false;
2166 }
2167 else if (!envval)
2168 {
2169 /* No argument - unset the environment variable */
2170 unsetenv(envvar);
2171 success = true;
2172 }
2173 else
2174 {
2175 /* Set variable to the value of the next argument */
2176 char *newval;
2177
2178 newval = psprintf("%s=%s", envvar, envval);
2179 putenv(newval);
2180 success = true;
2181
2182 /*
2183 * Do not free newval here, it will screw up the environment if
2184 * you do. See putenv man page for details. That means we leak a
2185 * bit of memory here, but not enough to worry about.
2186 */
2187 }
2188 free(envvar);
2189 free(envval);
2190 }
2191 else
2192 ignore_slash_options(scan_state);
2193
2194 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2195 }
2196
2197 /*
2198 * \sf -- show a function's source code
2199 */
2200 static backslashResult
exec_command_sf(PsqlScanState scan_state,bool active_branch,const char * cmd)2201 exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
2202 {
2203 backslashResult status = PSQL_CMD_SKIP_LINE;
2204
2205 if (active_branch)
2206 {
2207 bool show_linenumbers = (strcmp(cmd, "sf+") == 0);
2208 PQExpBuffer func_buf;
2209 char *func;
2210 Oid foid = InvalidOid;
2211
2212 func_buf = createPQExpBuffer();
2213 func = psql_scan_slash_option(scan_state,
2214 OT_WHOLE_LINE, NULL, true);
2215 if (pset.sversion < 80400)
2216 {
2217 char sverbuf[32];
2218
2219 psql_error("The server (version %s) does not support showing function source.\n",
2220 formatPGVersionNumber(pset.sversion, false,
2221 sverbuf, sizeof(sverbuf)));
2222 status = PSQL_CMD_ERROR;
2223 }
2224 else if (!func)
2225 {
2226 psql_error("function name is required\n");
2227 status = PSQL_CMD_ERROR;
2228 }
2229 else if (!lookup_object_oid(EditableFunction, func, &foid))
2230 {
2231 /* error already reported */
2232 status = PSQL_CMD_ERROR;
2233 }
2234 else if (!get_create_object_cmd(EditableFunction, foid, func_buf))
2235 {
2236 /* error already reported */
2237 status = PSQL_CMD_ERROR;
2238 }
2239 else
2240 {
2241 FILE *output;
2242 bool is_pager;
2243
2244 /* Select output stream: stdout, pager, or file */
2245 if (pset.queryFout == stdout)
2246 {
2247 /* count lines in function to see if pager is needed */
2248 int lineno = count_lines_in_buf(func_buf);
2249
2250 output = PageOutput(lineno, &(pset.popt.topt));
2251 is_pager = true;
2252 }
2253 else
2254 {
2255 /* use previously set output file, without pager */
2256 output = pset.queryFout;
2257 is_pager = false;
2258 }
2259
2260 if (show_linenumbers)
2261 {
2262 /*
2263 * lineno "1" should correspond to the first line of the
2264 * function body. We expect that pg_get_functiondef() will
2265 * emit that on a line beginning with "AS ", and that there
2266 * can be no such line before the real start of the function
2267 * body.
2268 */
2269 print_with_linenumbers(output, func_buf->data, "AS ");
2270 }
2271 else
2272 {
2273 /* just send the function definition to output */
2274 fputs(func_buf->data, output);
2275 }
2276
2277 if (is_pager)
2278 ClosePager(output);
2279 }
2280
2281 if (func)
2282 free(func);
2283 destroyPQExpBuffer(func_buf);
2284 }
2285 else
2286 ignore_slash_whole_line(scan_state);
2287
2288 return status;
2289 }
2290
2291 /*
2292 * \sv -- show a view's source code
2293 */
2294 static backslashResult
exec_command_sv(PsqlScanState scan_state,bool active_branch,const char * cmd)2295 exec_command_sv(PsqlScanState scan_state, bool active_branch, const char *cmd)
2296 {
2297 backslashResult status = PSQL_CMD_SKIP_LINE;
2298
2299 if (active_branch)
2300 {
2301 bool show_linenumbers = (strcmp(cmd, "sv+") == 0);
2302 PQExpBuffer view_buf;
2303 char *view;
2304 Oid view_oid = InvalidOid;
2305
2306 view_buf = createPQExpBuffer();
2307 view = psql_scan_slash_option(scan_state,
2308 OT_WHOLE_LINE, NULL, true);
2309 if (pset.sversion < 70400)
2310 {
2311 char sverbuf[32];
2312
2313 psql_error("The server (version %s) does not support showing view definitions.\n",
2314 formatPGVersionNumber(pset.sversion, false,
2315 sverbuf, sizeof(sverbuf)));
2316 status = PSQL_CMD_ERROR;
2317 }
2318 else if (!view)
2319 {
2320 psql_error("view name is required\n");
2321 status = PSQL_CMD_ERROR;
2322 }
2323 else if (!lookup_object_oid(EditableView, view, &view_oid))
2324 {
2325 /* error already reported */
2326 status = PSQL_CMD_ERROR;
2327 }
2328 else if (!get_create_object_cmd(EditableView, view_oid, view_buf))
2329 {
2330 /* error already reported */
2331 status = PSQL_CMD_ERROR;
2332 }
2333 else
2334 {
2335 FILE *output;
2336 bool is_pager;
2337
2338 /* Select output stream: stdout, pager, or file */
2339 if (pset.queryFout == stdout)
2340 {
2341 /* count lines in view to see if pager is needed */
2342 int lineno = count_lines_in_buf(view_buf);
2343
2344 output = PageOutput(lineno, &(pset.popt.topt));
2345 is_pager = true;
2346 }
2347 else
2348 {
2349 /* use previously set output file, without pager */
2350 output = pset.queryFout;
2351 is_pager = false;
2352 }
2353
2354 if (show_linenumbers)
2355 {
2356 /* add line numbers, numbering all lines */
2357 print_with_linenumbers(output, view_buf->data, NULL);
2358 }
2359 else
2360 {
2361 /* just send the view definition to output */
2362 fputs(view_buf->data, output);
2363 }
2364
2365 if (is_pager)
2366 ClosePager(output);
2367 }
2368
2369 if (view)
2370 free(view);
2371 destroyPQExpBuffer(view_buf);
2372 }
2373 else
2374 ignore_slash_whole_line(scan_state);
2375
2376 return status;
2377 }
2378
2379 /*
2380 * \t -- turn off table headers and row count
2381 */
2382 static backslashResult
exec_command_t(PsqlScanState scan_state,bool active_branch)2383 exec_command_t(PsqlScanState scan_state, bool active_branch)
2384 {
2385 bool success = true;
2386
2387 if (active_branch)
2388 {
2389 char *opt = psql_scan_slash_option(scan_state,
2390 OT_NORMAL, NULL, true);
2391
2392 success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
2393 free(opt);
2394 }
2395 else
2396 ignore_slash_options(scan_state);
2397
2398 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2399 }
2400
2401 /*
2402 * \T -- define html <table ...> attributes
2403 */
2404 static backslashResult
exec_command_T(PsqlScanState scan_state,bool active_branch)2405 exec_command_T(PsqlScanState scan_state, bool active_branch)
2406 {
2407 bool success = true;
2408
2409 if (active_branch)
2410 {
2411 char *value = psql_scan_slash_option(scan_state,
2412 OT_NORMAL, NULL, false);
2413
2414 success = do_pset("tableattr", value, &pset.popt, pset.quiet);
2415 free(value);
2416 }
2417 else
2418 ignore_slash_options(scan_state);
2419
2420 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2421 }
2422
2423 /*
2424 * \timing -- enable/disable timing of queries
2425 */
2426 static backslashResult
exec_command_timing(PsqlScanState scan_state,bool active_branch)2427 exec_command_timing(PsqlScanState scan_state, bool active_branch)
2428 {
2429 bool success = true;
2430
2431 if (active_branch)
2432 {
2433 char *opt = psql_scan_slash_option(scan_state,
2434 OT_NORMAL, NULL, false);
2435
2436 if (opt)
2437 success = ParseVariableBool(opt, "\\timing", &pset.timing);
2438 else
2439 pset.timing = !pset.timing;
2440 if (!pset.quiet)
2441 {
2442 if (pset.timing)
2443 puts(_("Timing is on."));
2444 else
2445 puts(_("Timing is off."));
2446 }
2447 free(opt);
2448 }
2449 else
2450 ignore_slash_options(scan_state);
2451
2452 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2453 }
2454
2455 /*
2456 * \unset -- unset variable
2457 */
2458 static backslashResult
exec_command_unset(PsqlScanState scan_state,bool active_branch,const char * cmd)2459 exec_command_unset(PsqlScanState scan_state, bool active_branch,
2460 const char *cmd)
2461 {
2462 bool success = true;
2463
2464 if (active_branch)
2465 {
2466 char *opt = psql_scan_slash_option(scan_state,
2467 OT_NORMAL, NULL, false);
2468
2469 if (!opt)
2470 {
2471 psql_error("\\%s: missing required argument\n", cmd);
2472 success = false;
2473 }
2474 else if (!SetVariable(pset.vars, opt, NULL))
2475 success = false;
2476
2477 free(opt);
2478 }
2479 else
2480 ignore_slash_options(scan_state);
2481
2482 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2483 }
2484
2485 /*
2486 * \w -- write query buffer to file
2487 */
2488 static backslashResult
exec_command_write(PsqlScanState scan_state,bool active_branch,const char * cmd,PQExpBuffer query_buf,PQExpBuffer previous_buf)2489 exec_command_write(PsqlScanState scan_state, bool active_branch,
2490 const char *cmd,
2491 PQExpBuffer query_buf, PQExpBuffer previous_buf)
2492 {
2493 backslashResult status = PSQL_CMD_SKIP_LINE;
2494
2495 if (active_branch)
2496 {
2497 char *fname = psql_scan_slash_option(scan_state,
2498 OT_FILEPIPE, NULL, true);
2499 FILE *fd = NULL;
2500 bool is_pipe = false;
2501
2502 if (!query_buf)
2503 {
2504 psql_error("no query buffer\n");
2505 status = PSQL_CMD_ERROR;
2506 }
2507 else
2508 {
2509 if (!fname)
2510 {
2511 psql_error("\\%s: missing required argument\n", cmd);
2512 status = PSQL_CMD_ERROR;
2513 }
2514 else
2515 {
2516 expand_tilde(&fname);
2517 if (fname[0] == '|')
2518 {
2519 is_pipe = true;
2520 disable_sigpipe_trap();
2521 fd = popen(&fname[1], "w");
2522 }
2523 else
2524 {
2525 canonicalize_path(fname);
2526 fd = fopen(fname, "w");
2527 }
2528 if (!fd)
2529 {
2530 psql_error("%s: %s\n", fname, strerror(errno));
2531 status = PSQL_CMD_ERROR;
2532 }
2533 }
2534 }
2535
2536 if (fd)
2537 {
2538 int result;
2539
2540 /*
2541 * We want to print the same thing \g would execute, but not to
2542 * change the query buffer state; so we can't use
2543 * copy_previous_query(). Also, beware of possibility that buffer
2544 * pointers are NULL.
2545 */
2546 if (query_buf && query_buf->len > 0)
2547 fprintf(fd, "%s\n", query_buf->data);
2548 else if (previous_buf && previous_buf->len > 0)
2549 fprintf(fd, "%s\n", previous_buf->data);
2550
2551 if (is_pipe)
2552 result = pclose(fd);
2553 else
2554 result = fclose(fd);
2555
2556 if (result == EOF)
2557 {
2558 psql_error("%s: %s\n", fname, strerror(errno));
2559 status = PSQL_CMD_ERROR;
2560 }
2561 }
2562
2563 if (is_pipe)
2564 restore_sigpipe_trap();
2565
2566 free(fname);
2567 }
2568 else
2569 ignore_slash_filepipe(scan_state);
2570
2571 return status;
2572 }
2573
2574 /*
2575 * \watch -- execute a query every N seconds
2576 */
2577 static backslashResult
exec_command_watch(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)2578 exec_command_watch(PsqlScanState scan_state, bool active_branch,
2579 PQExpBuffer query_buf, PQExpBuffer previous_buf)
2580 {
2581 bool success = true;
2582
2583 if (active_branch)
2584 {
2585 char *opt = psql_scan_slash_option(scan_state,
2586 OT_NORMAL, NULL, true);
2587 double sleep = 2;
2588
2589 /* Convert optional sleep-length argument */
2590 if (opt)
2591 {
2592 sleep = strtod(opt, NULL);
2593 if (sleep <= 0)
2594 sleep = 1;
2595 free(opt);
2596 }
2597
2598 /* If query_buf is empty, recall and execute previous query */
2599 copy_previous_query(query_buf, previous_buf);
2600
2601 success = do_watch(query_buf, sleep);
2602
2603 /* Reset the query buffer as though for \r */
2604 resetPQExpBuffer(query_buf);
2605 psql_scan_reset(scan_state);
2606 }
2607 else
2608 ignore_slash_options(scan_state);
2609
2610 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2611 }
2612
2613 /*
2614 * \x -- set or toggle expanded table representation
2615 */
2616 static backslashResult
exec_command_x(PsqlScanState scan_state,bool active_branch)2617 exec_command_x(PsqlScanState scan_state, bool active_branch)
2618 {
2619 bool success = true;
2620
2621 if (active_branch)
2622 {
2623 char *opt = psql_scan_slash_option(scan_state,
2624 OT_NORMAL, NULL, true);
2625
2626 success = do_pset("expanded", opt, &pset.popt, pset.quiet);
2627 free(opt);
2628 }
2629 else
2630 ignore_slash_options(scan_state);
2631
2632 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2633 }
2634
2635 /*
2636 * \z -- list table privileges (equivalent to \dp)
2637 */
2638 static backslashResult
exec_command_z(PsqlScanState scan_state,bool active_branch)2639 exec_command_z(PsqlScanState scan_state, bool active_branch)
2640 {
2641 bool success = true;
2642
2643 if (active_branch)
2644 {
2645 char *pattern = psql_scan_slash_option(scan_state,
2646 OT_NORMAL, NULL, true);
2647
2648 success = permissionsList(pattern);
2649 if (pattern)
2650 free(pattern);
2651 }
2652 else
2653 ignore_slash_options(scan_state);
2654
2655 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2656 }
2657
2658 /*
2659 * \! -- execute shell command
2660 */
2661 static backslashResult
exec_command_shell_escape(PsqlScanState scan_state,bool active_branch)2662 exec_command_shell_escape(PsqlScanState scan_state, bool active_branch)
2663 {
2664 bool success = true;
2665
2666 if (active_branch)
2667 {
2668 char *opt = psql_scan_slash_option(scan_state,
2669 OT_WHOLE_LINE, NULL, false);
2670
2671 success = do_shell(opt);
2672 free(opt);
2673 }
2674 else
2675 ignore_slash_whole_line(scan_state);
2676
2677 return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2678 }
2679
2680 /*
2681 * \? -- print help about backslash commands
2682 */
2683 static backslashResult
exec_command_slash_command_help(PsqlScanState scan_state,bool active_branch)2684 exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch)
2685 {
2686 if (active_branch)
2687 {
2688 char *opt0 = psql_scan_slash_option(scan_state,
2689 OT_NORMAL, NULL, false);
2690
2691 if (!opt0 || strcmp(opt0, "commands") == 0)
2692 slashUsage(pset.popt.topt.pager);
2693 else if (strcmp(opt0, "options") == 0)
2694 usage(pset.popt.topt.pager);
2695 else if (strcmp(opt0, "variables") == 0)
2696 helpVariables(pset.popt.topt.pager);
2697 else
2698 slashUsage(pset.popt.topt.pager);
2699
2700 if (opt0)
2701 free(opt0);
2702 }
2703 else
2704 ignore_slash_options(scan_state);
2705
2706 return PSQL_CMD_SKIP_LINE;
2707 }
2708
2709
2710 /*
2711 * Read and interpret an argument to the \connect slash command.
2712 *
2713 * Returns a malloc'd string, or NULL if no/empty argument.
2714 */
2715 static char *
read_connect_arg(PsqlScanState scan_state)2716 read_connect_arg(PsqlScanState scan_state)
2717 {
2718 char *result;
2719 char quote;
2720
2721 /*
2722 * Ideally we should treat the arguments as SQL identifiers. But for
2723 * backwards compatibility with 7.2 and older pg_dump files, we have to
2724 * take unquoted arguments verbatim (don't downcase them). For now,
2725 * double-quoted arguments may be stripped of double quotes (as if SQL
2726 * identifiers). By 7.4 or so, pg_dump files can be expected to
2727 * double-quote all mixed-case \connect arguments, and then we can get rid
2728 * of OT_SQLIDHACK.
2729 */
2730 result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, "e, true);
2731
2732 if (!result)
2733 return NULL;
2734
2735 if (quote)
2736 return result;
2737
2738 if (*result == '\0' || strcmp(result, "-") == 0)
2739 {
2740 free(result);
2741 return NULL;
2742 }
2743
2744 return result;
2745 }
2746
2747 /*
2748 * Read a boolean expression, return it as a PQExpBuffer string.
2749 *
2750 * Note: anything more or less than one token will certainly fail to be
2751 * parsed by ParseVariableBool, so we don't worry about complaining here.
2752 * This routine's return data structure will need to be rethought anyway
2753 * to support likely future extensions such as "\if defined VARNAME".
2754 */
2755 static PQExpBuffer
gather_boolean_expression(PsqlScanState scan_state)2756 gather_boolean_expression(PsqlScanState scan_state)
2757 {
2758 PQExpBuffer exp_buf = createPQExpBuffer();
2759 int num_options = 0;
2760 char *value;
2761
2762 /* collect all arguments for the conditional command into exp_buf */
2763 while ((value = psql_scan_slash_option(scan_state,
2764 OT_NORMAL, NULL, false)) != NULL)
2765 {
2766 /* add spaces between tokens */
2767 if (num_options > 0)
2768 appendPQExpBufferChar(exp_buf, ' ');
2769 appendPQExpBufferStr(exp_buf, value);
2770 num_options++;
2771 free(value);
2772 }
2773
2774 return exp_buf;
2775 }
2776
2777 /*
2778 * Read a boolean expression, return true if the expression
2779 * was a valid boolean expression that evaluated to true.
2780 * Otherwise return false.
2781 *
2782 * Note: conditional stack's top state must be active, else lexer will
2783 * fail to expand variables and backticks.
2784 */
2785 static bool
is_true_boolean_expression(PsqlScanState scan_state,const char * name)2786 is_true_boolean_expression(PsqlScanState scan_state, const char *name)
2787 {
2788 PQExpBuffer buf = gather_boolean_expression(scan_state);
2789 bool value = false;
2790 bool success = ParseVariableBool(buf->data, name, &value);
2791
2792 destroyPQExpBuffer(buf);
2793 return success && value;
2794 }
2795
2796 /*
2797 * Read a boolean expression, but do nothing with it.
2798 *
2799 * Note: conditional stack's top state must be INACTIVE, else lexer will
2800 * expand variables and backticks, which we do not want here.
2801 */
2802 static void
ignore_boolean_expression(PsqlScanState scan_state)2803 ignore_boolean_expression(PsqlScanState scan_state)
2804 {
2805 PQExpBuffer buf = gather_boolean_expression(scan_state);
2806
2807 destroyPQExpBuffer(buf);
2808 }
2809
2810 /*
2811 * Read and discard "normal" slash command options.
2812 *
2813 * This should be used for inactive-branch processing of any slash command
2814 * that eats one or more OT_NORMAL, OT_SQLID, or OT_SQLIDHACK parameters.
2815 * We don't need to worry about exactly how many it would eat, since the
2816 * cleanup logic in HandleSlashCmds would silently discard any extras anyway.
2817 */
2818 static void
ignore_slash_options(PsqlScanState scan_state)2819 ignore_slash_options(PsqlScanState scan_state)
2820 {
2821 char *arg;
2822
2823 while ((arg = psql_scan_slash_option(scan_state,
2824 OT_NORMAL, NULL, false)) != NULL)
2825 free(arg);
2826 }
2827
2828 /*
2829 * Read and discard FILEPIPE slash command argument.
2830 *
2831 * This *MUST* be used for inactive-branch processing of any slash command
2832 * that takes an OT_FILEPIPE option. Otherwise we might consume a different
2833 * amount of option text in active and inactive cases.
2834 */
2835 static void
ignore_slash_filepipe(PsqlScanState scan_state)2836 ignore_slash_filepipe(PsqlScanState scan_state)
2837 {
2838 char *arg = psql_scan_slash_option(scan_state,
2839 OT_FILEPIPE, NULL, false);
2840
2841 if (arg)
2842 free(arg);
2843 }
2844
2845 /*
2846 * Read and discard whole-line slash command argument.
2847 *
2848 * This *MUST* be used for inactive-branch processing of any slash command
2849 * that takes an OT_WHOLE_LINE option. Otherwise we might consume a different
2850 * amount of option text in active and inactive cases.
2851 */
2852 static void
ignore_slash_whole_line(PsqlScanState scan_state)2853 ignore_slash_whole_line(PsqlScanState scan_state)
2854 {
2855 char *arg = psql_scan_slash_option(scan_state,
2856 OT_WHOLE_LINE, NULL, false);
2857
2858 if (arg)
2859 free(arg);
2860 }
2861
2862 /*
2863 * Return true if the command given is a branching command.
2864 */
2865 static bool
is_branching_command(const char * cmd)2866 is_branching_command(const char *cmd)
2867 {
2868 return (strcmp(cmd, "if") == 0 ||
2869 strcmp(cmd, "elif") == 0 ||
2870 strcmp(cmd, "else") == 0 ||
2871 strcmp(cmd, "endif") == 0);
2872 }
2873
2874 /*
2875 * Prepare to possibly restore query buffer to its current state
2876 * (cf. discard_query_text).
2877 *
2878 * We need to remember the length of the query buffer, and the lexer's
2879 * notion of the parenthesis nesting depth.
2880 */
2881 static void
save_query_text_state(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)2882 save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
2883 PQExpBuffer query_buf)
2884 {
2885 if (query_buf)
2886 conditional_stack_set_query_len(cstack, query_buf->len);
2887 conditional_stack_set_paren_depth(cstack,
2888 psql_scan_get_paren_depth(scan_state));
2889 }
2890
2891 /*
2892 * Discard any query text absorbed during an inactive conditional branch.
2893 *
2894 * We must discard data that was appended to query_buf during an inactive
2895 * \if branch. We don't have to do anything there if there's no query_buf.
2896 *
2897 * Also, reset the lexer state to the same paren depth there was before.
2898 * (The rest of its state doesn't need attention, since we could not be
2899 * inside a comment or literal or partial token.)
2900 */
2901 static void
discard_query_text(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)2902 discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
2903 PQExpBuffer query_buf)
2904 {
2905 if (query_buf)
2906 {
2907 int new_len = conditional_stack_get_query_len(cstack);
2908
2909 Assert(new_len >= 0 && new_len <= query_buf->len);
2910 query_buf->len = new_len;
2911 query_buf->data[new_len] = '\0';
2912 }
2913 psql_scan_set_paren_depth(scan_state,
2914 conditional_stack_get_paren_depth(cstack));
2915 }
2916
2917 /*
2918 * If query_buf is empty, copy previous_buf into it.
2919 *
2920 * This is used by various slash commands for which re-execution of a
2921 * previous query is a common usage. For convenience, we allow the
2922 * case of query_buf == NULL (and do nothing).
2923 */
2924 static void
copy_previous_query(PQExpBuffer query_buf,PQExpBuffer previous_buf)2925 copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
2926 {
2927 if (query_buf && query_buf->len == 0)
2928 appendPQExpBufferStr(query_buf, previous_buf->data);
2929 }
2930
2931 /*
2932 * Ask the user for a password; 'username' is the username the
2933 * password is for, if one has been explicitly specified. Returns a
2934 * malloc'd string.
2935 */
2936 static char *
prompt_for_password(const char * username)2937 prompt_for_password(const char *username)
2938 {
2939 char buf[100];
2940
2941 if (username == NULL)
2942 simple_prompt("Password: ", buf, sizeof(buf), false);
2943 else
2944 {
2945 char *prompt_text;
2946
2947 prompt_text = psprintf(_("Password for user %s: "), username);
2948 simple_prompt(prompt_text, buf, sizeof(buf), false);
2949 free(prompt_text);
2950 }
2951 return pg_strdup(buf);
2952 }
2953
2954 static bool
param_is_newly_set(const char * old_val,const char * new_val)2955 param_is_newly_set(const char *old_val, const char *new_val)
2956 {
2957 if (new_val == NULL)
2958 return false;
2959
2960 if (old_val == NULL || strcmp(old_val, new_val) != 0)
2961 return true;
2962
2963 return false;
2964 }
2965
2966 /*
2967 * do_connect -- handler for \connect
2968 *
2969 * Connects to a database with given parameters. Absent an established
2970 * connection, all parameters are required. Given -reuse-previous=off or a
2971 * connection string without -reuse-previous=on, NULL values will pass through
2972 * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
2973 * values will be replaced with the ones in the current connection.
2974 *
2975 * In interactive mode, if connection fails with the given parameters,
2976 * the old connection will be kept.
2977 */
2978 static bool
do_connect(enum trivalue reuse_previous_specification,char * dbname,char * user,char * host,char * port)2979 do_connect(enum trivalue reuse_previous_specification,
2980 char *dbname, char *user, char *host, char *port)
2981 {
2982 PGconn *o_conn = pset.db,
2983 *n_conn = NULL;
2984 PQconninfoOption *cinfo;
2985 int nconnopts = 0;
2986 bool same_host = false;
2987 char *password = NULL;
2988 char *client_encoding;
2989 bool success = true;
2990 bool keep_password = true;
2991 bool has_connection_string;
2992 bool reuse_previous;
2993
2994 if (!o_conn && (!dbname || !user || !host || !port))
2995 {
2996 /*
2997 * We don't know the supplied connection parameters and don't want to
2998 * connect to the wrong database by using defaults, so require all
2999 * parameters to be specified.
3000 */
3001 psql_error("All connection parameters must be supplied because no "
3002 "database connection exists\n");
3003 return false;
3004 }
3005
3006 has_connection_string = dbname ?
3007 recognized_connection_string(dbname) : false;
3008 switch (reuse_previous_specification)
3009 {
3010 case TRI_YES:
3011 reuse_previous = true;
3012 break;
3013 case TRI_NO:
3014 reuse_previous = false;
3015 break;
3016 default:
3017 reuse_previous = !has_connection_string;
3018 break;
3019 }
3020
3021 /* If the old connection does not exist, there is nothing to reuse. */
3022 if (!o_conn)
3023 reuse_previous = false;
3024
3025 /* Silently ignore arguments subsequent to a connection string. */
3026 if (has_connection_string)
3027 {
3028 user = NULL;
3029 host = NULL;
3030 port = NULL;
3031 }
3032
3033 /*
3034 * If we intend to re-use connection parameters, collect them out of the
3035 * old connection, then replace individual values as necessary. Otherwise,
3036 * obtain a PQconninfoOption array containing libpq's defaults, and modify
3037 * that. Note this function assumes that PQconninfo, PQconndefaults, and
3038 * PQconninfoParse will all produce arrays containing the same options in
3039 * the same order.
3040 */
3041 if (reuse_previous)
3042 cinfo = PQconninfo(o_conn);
3043 else
3044 cinfo = PQconndefaults();
3045
3046 if (cinfo)
3047 {
3048 if (has_connection_string)
3049 {
3050 /* Parse the connstring and insert values into cinfo */
3051 PQconninfoOption *replcinfo;
3052 char *errmsg;
3053
3054 replcinfo = PQconninfoParse(dbname, &errmsg);
3055 if (replcinfo)
3056 {
3057 PQconninfoOption *ci;
3058 PQconninfoOption *replci;
3059 bool have_password = false;
3060
3061 for (ci = cinfo, replci = replcinfo;
3062 ci->keyword && replci->keyword;
3063 ci++, replci++)
3064 {
3065 Assert(strcmp(ci->keyword, replci->keyword) == 0);
3066 /* Insert value from connstring if one was provided */
3067 if (replci->val)
3068 {
3069 /*
3070 * We know that both val strings were allocated by
3071 * libpq, so the least messy way to avoid memory leaks
3072 * is to swap them.
3073 */
3074 char *swap = replci->val;
3075
3076 replci->val = ci->val;
3077 ci->val = swap;
3078
3079 /*
3080 * Check whether connstring provides options affecting
3081 * password re-use. While any change in user, host,
3082 * hostaddr, or port causes us to ignore the old
3083 * connection's password, we don't force that for
3084 * dbname, since passwords aren't database-specific.
3085 */
3086 if (replci->val == NULL ||
3087 strcmp(ci->val, replci->val) != 0)
3088 {
3089 if (strcmp(replci->keyword, "user") == 0 ||
3090 strcmp(replci->keyword, "host") == 0 ||
3091 strcmp(replci->keyword, "hostaddr") == 0 ||
3092 strcmp(replci->keyword, "port") == 0)
3093 keep_password = false;
3094 }
3095 /* Also note whether connstring contains a password. */
3096 if (strcmp(replci->keyword, "password") == 0)
3097 have_password = true;
3098 }
3099 else if (!reuse_previous)
3100 {
3101 /*
3102 * When we have a connstring and are not re-using
3103 * parameters, swap *all* entries, even those not set
3104 * by the connstring. This avoids absorbing
3105 * environment-dependent defaults from the result of
3106 * PQconndefaults(). We don't want to do that because
3107 * they'd override service-file entries if the
3108 * connstring specifies a service parameter, whereas
3109 * the priority should be the other way around. libpq
3110 * can certainly recompute any defaults we don't pass
3111 * here. (In this situation, it's a bit wasteful to
3112 * have called PQconndefaults() at all, but not doing
3113 * so would require yet another major code path here.)
3114 */
3115 replci->val = ci->val;
3116 ci->val = NULL;
3117 }
3118 }
3119 Assert(ci->keyword == NULL && replci->keyword == NULL);
3120
3121 /* While here, determine how many option slots there are */
3122 nconnopts = ci - cinfo;
3123
3124 PQconninfoFree(replcinfo);
3125
3126 /*
3127 * If the connstring contains a password, tell the loop below
3128 * that we may use it, regardless of other settings (i.e.,
3129 * cinfo's password is no longer an "old" password).
3130 */
3131 if (have_password)
3132 keep_password = true;
3133
3134 /* Don't let code below try to inject dbname into params. */
3135 dbname = NULL;
3136 }
3137 else
3138 {
3139 /* PQconninfoParse failed */
3140 if (errmsg)
3141 {
3142 psql_error("%s", errmsg);
3143 PQfreemem(errmsg);
3144 }
3145 else
3146 psql_error("out of memory\n");
3147 success = false;
3148 }
3149 }
3150 else
3151 {
3152 /*
3153 * If dbname isn't a connection string, then we'll inject it and
3154 * the other parameters into the keyword array below. (We can't
3155 * easily insert them into the cinfo array because of memory
3156 * management issues: PQconninfoFree would misbehave on Windows.)
3157 * However, to avoid dependencies on the order in which parameters
3158 * appear in the array, make a preliminary scan to set
3159 * keep_password and same_host correctly.
3160 *
3161 * While any change in user, host, or port causes us to ignore the
3162 * old connection's password, we don't force that for dbname,
3163 * since passwords aren't database-specific.
3164 */
3165 PQconninfoOption *ci;
3166
3167 for (ci = cinfo; ci->keyword; ci++)
3168 {
3169 if (user && strcmp(ci->keyword, "user") == 0)
3170 {
3171 if (!(ci->val && strcmp(user, ci->val) == 0))
3172 keep_password = false;
3173 }
3174 else if (host && strcmp(ci->keyword, "host") == 0)
3175 {
3176 if (ci->val && strcmp(host, ci->val) == 0)
3177 same_host = true;
3178 else
3179 keep_password = false;
3180 }
3181 else if (port && strcmp(ci->keyword, "port") == 0)
3182 {
3183 if (!(ci->val && strcmp(port, ci->val) == 0))
3184 keep_password = false;
3185 }
3186 }
3187
3188 /* While here, determine how many option slots there are */
3189 nconnopts = ci - cinfo;
3190 }
3191 }
3192 else
3193 {
3194 /* We failed to create the cinfo structure */
3195 psql_error("out of memory\n");
3196 success = false;
3197 }
3198
3199 /*
3200 * If the user asked to be prompted for a password, ask for one now. If
3201 * not, use the password from the old connection, provided the username
3202 * etc have not changed. Otherwise, try to connect without a password
3203 * first, and then ask for a password if needed.
3204 *
3205 * XXX: this behavior leads to spurious connection attempts recorded in
3206 * the postmaster's log. But libpq offers no API that would let us obtain
3207 * a password and then continue with the first connection attempt.
3208 */
3209 if (pset.getPassword == TRI_YES && success)
3210 {
3211 password = prompt_for_password(user);
3212 }
3213
3214 /*
3215 * Consider whether to force client_encoding to "auto" (overriding
3216 * anything in the connection string). We do so if we have a terminal
3217 * connection and there is no PGCLIENTENCODING environment setting.
3218 */
3219 if (pset.notty || getenv("PGCLIENTENCODING"))
3220 client_encoding = NULL;
3221 else
3222 client_encoding = "auto";
3223
3224 /* Loop till we have a connection or fail, which we might've already */
3225 while (success)
3226 {
3227 const char **keywords = pg_malloc((nconnopts + 1) * sizeof(*keywords));
3228 const char **values = pg_malloc((nconnopts + 1) * sizeof(*values));
3229 int paramnum = 0;
3230 PQconninfoOption *ci;
3231
3232 /*
3233 * Copy non-default settings into the PQconnectdbParams parameter
3234 * arrays; but inject any values specified old-style, as well as any
3235 * interactively-obtained password, and a couple of fields we want to
3236 * set forcibly.
3237 *
3238 * If you change this code, see also the initial-connection code in
3239 * main().
3240 */
3241 for (ci = cinfo; ci->keyword; ci++)
3242 {
3243 keywords[paramnum] = ci->keyword;
3244
3245 if (dbname && strcmp(ci->keyword, "dbname") == 0)
3246 values[paramnum++] = dbname;
3247 else if (user && strcmp(ci->keyword, "user") == 0)
3248 values[paramnum++] = user;
3249 else if (host && strcmp(ci->keyword, "host") == 0)
3250 values[paramnum++] = host;
3251 else if (host && !same_host && strcmp(ci->keyword, "hostaddr") == 0)
3252 {
3253 /* If we're changing the host value, drop any old hostaddr */
3254 values[paramnum++] = NULL;
3255 }
3256 else if (port && strcmp(ci->keyword, "port") == 0)
3257 values[paramnum++] = port;
3258 /* If !keep_password, we unconditionally drop old password */
3259 else if ((password || !keep_password) &&
3260 strcmp(ci->keyword, "password") == 0)
3261 values[paramnum++] = password;
3262 else if (strcmp(ci->keyword, "fallback_application_name") == 0)
3263 values[paramnum++] = pset.progname;
3264 else if (client_encoding &&
3265 strcmp(ci->keyword, "client_encoding") == 0)
3266 values[paramnum++] = client_encoding;
3267 else if (ci->val)
3268 values[paramnum++] = ci->val;
3269 /* else, don't bother making libpq parse this keyword */
3270 }
3271 /* add array terminator */
3272 keywords[paramnum] = NULL;
3273 values[paramnum] = NULL;
3274
3275 /* Note we do not want libpq to re-expand the dbname parameter */
3276 n_conn = PQconnectdbParams(keywords, values, false);
3277
3278 pg_free(keywords);
3279 pg_free(values);
3280
3281 if (PQstatus(n_conn) == CONNECTION_OK)
3282 break;
3283
3284 /*
3285 * Connection attempt failed; either retry the connection attempt with
3286 * a new password, or give up.
3287 */
3288 if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
3289 {
3290 /*
3291 * Prompt for password using the username we actually connected
3292 * with --- it might've come out of "dbname" rather than "user".
3293 */
3294 password = prompt_for_password(PQuser(n_conn));
3295 PQfinish(n_conn);
3296 n_conn = NULL;
3297 continue;
3298 }
3299
3300 /*
3301 * We'll report the error below ... unless n_conn is NULL, indicating
3302 * that libpq didn't have enough memory to make a PGconn.
3303 */
3304 if (n_conn == NULL)
3305 psql_error("out of memory\n");
3306
3307 success = false;
3308 } /* end retry loop */
3309
3310 /* Release locally allocated data, whether we succeeded or not */
3311 if (password)
3312 pg_free(password);
3313 if (cinfo)
3314 PQconninfoFree(cinfo);
3315
3316 if (!success)
3317 {
3318 /*
3319 * Failed to connect to the database. In interactive mode, keep the
3320 * previous connection to the DB; in scripting mode, close our
3321 * previous connection as well.
3322 */
3323 if (pset.cur_cmd_interactive)
3324 {
3325 if (n_conn)
3326 {
3327 psql_error("%s", PQerrorMessage(n_conn));
3328 PQfinish(n_conn);
3329 }
3330
3331 /* pset.db is left unmodified */
3332 if (o_conn)
3333 psql_error("Previous connection kept\n");
3334 }
3335 else
3336 {
3337 if (n_conn)
3338 {
3339 psql_error("\\connect: %s", PQerrorMessage(n_conn));
3340 PQfinish(n_conn);
3341 }
3342
3343 if (o_conn)
3344 {
3345 /*
3346 * Transition to having no connection. Keep this bit in sync
3347 * with CheckConnection().
3348 */
3349 PQfinish(o_conn);
3350 pset.db = NULL;
3351 ResetCancelConn();
3352 UnsyncVariables();
3353 }
3354 }
3355
3356 return false;
3357 }
3358
3359 /*
3360 * Replace the old connection with the new one, and update
3361 * connection-dependent variables. Keep the resynchronization logic in
3362 * sync with CheckConnection().
3363 */
3364 PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
3365 pset.db = n_conn;
3366 SyncVariables();
3367 connection_warnings(false); /* Must be after SyncVariables */
3368
3369 /* Tell the user about the new connection */
3370 if (!pset.quiet)
3371 {
3372 if (!o_conn ||
3373 param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
3374 param_is_newly_set(PQport(o_conn), PQport(pset.db)))
3375 {
3376 char *host = PQhost(pset.db);
3377
3378 /* If the host is an absolute path, the connection is via socket */
3379 if (is_absolute_path(host))
3380 printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
3381 PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3382 else
3383 printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
3384 PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3385 }
3386 else
3387 printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
3388 PQdb(pset.db), PQuser(pset.db));
3389 }
3390
3391 if (o_conn)
3392 PQfinish(o_conn);
3393 return true;
3394 }
3395
3396
3397 void
connection_warnings(bool in_startup)3398 connection_warnings(bool in_startup)
3399 {
3400 if (!pset.quiet && !pset.notty)
3401 {
3402 int client_ver = PG_VERSION_NUM;
3403 char cverbuf[32];
3404 char sverbuf[32];
3405
3406 if (pset.sversion != client_ver)
3407 {
3408 const char *server_version;
3409
3410 /* Try to get full text form, might include "devel" etc */
3411 server_version = PQparameterStatus(pset.db, "server_version");
3412 /* Otherwise fall back on pset.sversion */
3413 if (!server_version)
3414 {
3415 formatPGVersionNumber(pset.sversion, true,
3416 sverbuf, sizeof(sverbuf));
3417 server_version = sverbuf;
3418 }
3419
3420 printf(_("%s (%s, server %s)\n"),
3421 pset.progname, PG_VERSION, server_version);
3422 }
3423 /* For version match, only print psql banner on startup. */
3424 else if (in_startup)
3425 printf("%s (%s)\n", pset.progname, PG_VERSION);
3426
3427 if (pset.sversion / 100 > client_ver / 100)
3428 printf(_("WARNING: %s major version %s, server major version %s.\n"
3429 " Some psql features might not work.\n"),
3430 pset.progname,
3431 formatPGVersionNumber(client_ver, false,
3432 cverbuf, sizeof(cverbuf)),
3433 formatPGVersionNumber(pset.sversion, false,
3434 sverbuf, sizeof(sverbuf)));
3435
3436 #ifdef WIN32
3437 if (in_startup)
3438 checkWin32Codepage();
3439 #endif
3440 printSSLInfo();
3441 }
3442 }
3443
3444
3445 /*
3446 * printSSLInfo
3447 *
3448 * Prints information about the current SSL connection, if SSL is in use
3449 */
3450 static void
printSSLInfo(void)3451 printSSLInfo(void)
3452 {
3453 const char *protocol;
3454 const char *cipher;
3455 const char *bits;
3456 const char *compression;
3457
3458 if (!PQsslInUse(pset.db))
3459 return; /* no SSL */
3460
3461 protocol = PQsslAttribute(pset.db, "protocol");
3462 cipher = PQsslAttribute(pset.db, "cipher");
3463 bits = PQsslAttribute(pset.db, "key_bits");
3464 compression = PQsslAttribute(pset.db, "compression");
3465
3466 printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
3467 protocol ? protocol : _("unknown"),
3468 cipher ? cipher : _("unknown"),
3469 bits ? bits : _("unknown"),
3470 (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
3471 }
3472
3473
3474 /*
3475 * checkWin32Codepage
3476 *
3477 * Prints a warning when win32 console codepage differs from Windows codepage
3478 */
3479 #ifdef WIN32
3480 static void
checkWin32Codepage(void)3481 checkWin32Codepage(void)
3482 {
3483 unsigned int wincp,
3484 concp;
3485
3486 wincp = GetACP();
3487 concp = GetConsoleCP();
3488 if (wincp != concp)
3489 {
3490 printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
3491 " 8-bit characters might not work correctly. See psql reference\n"
3492 " page \"Notes for Windows users\" for details.\n"),
3493 concp, wincp);
3494 }
3495 }
3496 #endif
3497
3498
3499 /*
3500 * SyncVariables
3501 *
3502 * Make psql's internal variables agree with connection state upon
3503 * establishing a new connection.
3504 */
3505 void
SyncVariables(void)3506 SyncVariables(void)
3507 {
3508 char vbuf[32];
3509 const char *server_version;
3510
3511 /* get stuff from connection */
3512 pset.encoding = PQclientEncoding(pset.db);
3513 pset.popt.topt.encoding = pset.encoding;
3514 pset.sversion = PQserverVersion(pset.db);
3515
3516 SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
3517 SetVariable(pset.vars, "USER", PQuser(pset.db));
3518 SetVariable(pset.vars, "HOST", PQhost(pset.db));
3519 SetVariable(pset.vars, "PORT", PQport(pset.db));
3520 SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
3521
3522 /* this bit should match connection_warnings(): */
3523 /* Try to get full text form of version, might include "devel" etc */
3524 server_version = PQparameterStatus(pset.db, "server_version");
3525 /* Otherwise fall back on pset.sversion */
3526 if (!server_version)
3527 {
3528 formatPGVersionNumber(pset.sversion, true, vbuf, sizeof(vbuf));
3529 server_version = vbuf;
3530 }
3531 SetVariable(pset.vars, "SERVER_VERSION_NAME", server_version);
3532
3533 snprintf(vbuf, sizeof(vbuf), "%d", pset.sversion);
3534 SetVariable(pset.vars, "SERVER_VERSION_NUM", vbuf);
3535
3536 /* send stuff to it, too */
3537 PQsetErrorVerbosity(pset.db, pset.verbosity);
3538 PQsetErrorContextVisibility(pset.db, pset.show_context);
3539 }
3540
3541 /*
3542 * UnsyncVariables
3543 *
3544 * Clear variables that should be not be set when there is no connection.
3545 */
3546 void
UnsyncVariables(void)3547 UnsyncVariables(void)
3548 {
3549 SetVariable(pset.vars, "DBNAME", NULL);
3550 SetVariable(pset.vars, "USER", NULL);
3551 SetVariable(pset.vars, "HOST", NULL);
3552 SetVariable(pset.vars, "PORT", NULL);
3553 SetVariable(pset.vars, "ENCODING", NULL);
3554 SetVariable(pset.vars, "SERVER_VERSION_NAME", NULL);
3555 SetVariable(pset.vars, "SERVER_VERSION_NUM", NULL);
3556 }
3557
3558
3559 /*
3560 * do_edit -- handler for \e
3561 *
3562 * If you do not specify a filename, the current query buffer will be copied
3563 * into a temporary one.
3564 */
3565 static bool
editFile(const char * fname,int lineno)3566 editFile(const char *fname, int lineno)
3567 {
3568 const char *editorName;
3569 const char *editor_lineno_arg = NULL;
3570 char *sys;
3571 int result;
3572
3573 Assert(fname != NULL);
3574
3575 /* Find an editor to use */
3576 editorName = getenv("PSQL_EDITOR");
3577 if (!editorName)
3578 editorName = getenv("EDITOR");
3579 if (!editorName)
3580 editorName = getenv("VISUAL");
3581 if (!editorName)
3582 editorName = DEFAULT_EDITOR;
3583
3584 /* Get line number argument, if we need it. */
3585 if (lineno > 0)
3586 {
3587 editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
3588 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
3589 if (!editor_lineno_arg)
3590 editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
3591 #endif
3592 if (!editor_lineno_arg)
3593 {
3594 psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n");
3595 return false;
3596 }
3597 }
3598
3599 /*
3600 * On Unix the EDITOR value should *not* be quoted, since it might include
3601 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
3602 * if necessary. But this policy is not very workable on Windows, due to
3603 * severe brain damage in their command shell plus the fact that standard
3604 * program paths include spaces.
3605 */
3606 #ifndef WIN32
3607 if (lineno > 0)
3608 sys = psprintf("exec %s %s%d '%s'",
3609 editorName, editor_lineno_arg, lineno, fname);
3610 else
3611 sys = psprintf("exec %s '%s'",
3612 editorName, fname);
3613 #else
3614 if (lineno > 0)
3615 sys = psprintf("\"%s\" %s%d \"%s\"",
3616 editorName, editor_lineno_arg, lineno, fname);
3617 else
3618 sys = psprintf("\"%s\" \"%s\"",
3619 editorName, fname);
3620 #endif
3621 result = system(sys);
3622 if (result == -1)
3623 psql_error("could not start editor \"%s\"\n", editorName);
3624 else if (result == 127)
3625 psql_error("could not start /bin/sh\n");
3626 free(sys);
3627
3628 return result == 0;
3629 }
3630
3631
3632 /* call this one */
3633 static bool
do_edit(const char * filename_arg,PQExpBuffer query_buf,int lineno,bool * edited)3634 do_edit(const char *filename_arg, PQExpBuffer query_buf,
3635 int lineno, bool *edited)
3636 {
3637 char fnametmp[MAXPGPATH];
3638 FILE *stream = NULL;
3639 const char *fname;
3640 bool error = false;
3641 int fd;
3642 struct stat before,
3643 after;
3644
3645 if (filename_arg)
3646 fname = filename_arg;
3647 else
3648 {
3649 /* make a temp file to edit */
3650 #ifndef WIN32
3651 const char *tmpdir = getenv("TMPDIR");
3652
3653 if (!tmpdir)
3654 tmpdir = "/tmp";
3655 #else
3656 char tmpdir[MAXPGPATH];
3657 int ret;
3658
3659 ret = GetTempPath(MAXPGPATH, tmpdir);
3660 if (ret == 0 || ret > MAXPGPATH)
3661 {
3662 psql_error("could not locate temporary directory: %s\n",
3663 !ret ? strerror(errno) : "");
3664 return false;
3665 }
3666 #endif
3667
3668 /*
3669 * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
3670 * current directory to the supplied path unless we use only
3671 * backslashes, so we do that.
3672 */
3673 #ifndef WIN32
3674 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3675 "/", (int) getpid());
3676 #else
3677 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3678 "" /* trailing separator already present */ , (int) getpid());
3679 #endif
3680
3681 fname = (const char *) fnametmp;
3682
3683 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
3684 if (fd != -1)
3685 stream = fdopen(fd, "w");
3686
3687 if (fd == -1 || !stream)
3688 {
3689 psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
3690 error = true;
3691 }
3692 else
3693 {
3694 unsigned int ql = query_buf->len;
3695
3696 if (ql == 0 || query_buf->data[ql - 1] != '\n')
3697 {
3698 appendPQExpBufferChar(query_buf, '\n');
3699 ql++;
3700 }
3701
3702 if (fwrite(query_buf->data, 1, ql, stream) != ql)
3703 {
3704 psql_error("%s: %s\n", fname, strerror(errno));
3705
3706 if (fclose(stream) != 0)
3707 psql_error("%s: %s\n", fname, strerror(errno));
3708
3709 if (remove(fname) != 0)
3710 psql_error("%s: %s\n", fname, strerror(errno));
3711
3712 error = true;
3713 }
3714 else if (fclose(stream) != 0)
3715 {
3716 psql_error("%s: %s\n", fname, strerror(errno));
3717 if (remove(fname) != 0)
3718 psql_error("%s: %s\n", fname, strerror(errno));
3719 error = true;
3720 }
3721 else
3722 {
3723 struct utimbuf ut;
3724
3725 /*
3726 * Try to set the file modification time of the temporary file
3727 * a few seconds in the past. Otherwise, the low granularity
3728 * (one second, or even worse on some filesystems) that we can
3729 * portably measure with stat(2) could lead us to not
3730 * recognize a modification, if the user typed very quickly.
3731 *
3732 * This is a rather unlikely race condition, so don't error
3733 * out if the utime(2) call fails --- that would make the cure
3734 * worse than the disease.
3735 */
3736 ut.modtime = ut.actime = time(NULL) - 2;
3737 (void) utime(fname, &ut);
3738 }
3739 }
3740 }
3741
3742 if (!error && stat(fname, &before) != 0)
3743 {
3744 psql_error("%s: %s\n", fname, strerror(errno));
3745 error = true;
3746 }
3747
3748 /* call editor */
3749 if (!error)
3750 error = !editFile(fname, lineno);
3751
3752 if (!error && stat(fname, &after) != 0)
3753 {
3754 psql_error("%s: %s\n", fname, strerror(errno));
3755 error = true;
3756 }
3757
3758 /* file was edited if the size or modification time has changed */
3759 if (!error &&
3760 (before.st_size != after.st_size ||
3761 before.st_mtime != after.st_mtime))
3762 {
3763 stream = fopen(fname, PG_BINARY_R);
3764 if (!stream)
3765 {
3766 psql_error("%s: %s\n", fname, strerror(errno));
3767 error = true;
3768 }
3769 else
3770 {
3771 /* read file back into query_buf */
3772 char line[1024];
3773
3774 resetPQExpBuffer(query_buf);
3775 while (fgets(line, sizeof(line), stream) != NULL)
3776 appendPQExpBufferStr(query_buf, line);
3777
3778 if (ferror(stream))
3779 {
3780 psql_error("%s: %s\n", fname, strerror(errno));
3781 error = true;
3782 }
3783 else if (edited)
3784 {
3785 *edited = true;
3786 }
3787
3788 fclose(stream);
3789 }
3790 }
3791
3792 /* remove temp file */
3793 if (!filename_arg)
3794 {
3795 if (remove(fname) == -1)
3796 {
3797 psql_error("%s: %s\n", fname, strerror(errno));
3798 error = true;
3799 }
3800 }
3801
3802 return !error;
3803 }
3804
3805
3806
3807 /*
3808 * process_file
3809 *
3810 * Reads commands from filename and passes them to the main processing loop.
3811 * Handler for \i and \ir, but can be used for other things as well. Returns
3812 * MainLoop() error code.
3813 *
3814 * If use_relative_path is true and filename is not an absolute path, then open
3815 * the file from where the currently processed file (if any) is located.
3816 */
3817 int
process_file(char * filename,bool use_relative_path)3818 process_file(char *filename, bool use_relative_path)
3819 {
3820 FILE *fd;
3821 int result;
3822 char *oldfilename;
3823 char relpath[MAXPGPATH];
3824
3825 if (!filename)
3826 {
3827 fd = stdin;
3828 filename = NULL;
3829 }
3830 else if (strcmp(filename, "-") != 0)
3831 {
3832 canonicalize_path(filename);
3833
3834 /*
3835 * If we were asked to resolve the pathname relative to the location
3836 * of the currently executing script, and there is one, and this is a
3837 * relative pathname, then prepend all but the last pathname component
3838 * of the current script to this pathname.
3839 */
3840 if (use_relative_path && pset.inputfile &&
3841 !is_absolute_path(filename) && !has_drive_prefix(filename))
3842 {
3843 strlcpy(relpath, pset.inputfile, sizeof(relpath));
3844 get_parent_directory(relpath);
3845 join_path_components(relpath, relpath, filename);
3846 canonicalize_path(relpath);
3847
3848 filename = relpath;
3849 }
3850
3851 fd = fopen(filename, PG_BINARY_R);
3852
3853 if (!fd)
3854 {
3855 psql_error("%s: %s\n", filename, strerror(errno));
3856 return EXIT_FAILURE;
3857 }
3858 }
3859 else
3860 {
3861 fd = stdin;
3862 filename = "<stdin>"; /* for future error messages */
3863 }
3864
3865 oldfilename = pset.inputfile;
3866 pset.inputfile = filename;
3867
3868 result = MainLoop(fd);
3869
3870 if (fd != stdin)
3871 fclose(fd);
3872
3873 pset.inputfile = oldfilename;
3874 return result;
3875 }
3876
3877
3878
3879 static const char *
_align2string(enum printFormat in)3880 _align2string(enum printFormat in)
3881 {
3882 switch (in)
3883 {
3884 case PRINT_NOTHING:
3885 return "nothing";
3886 break;
3887 case PRINT_UNALIGNED:
3888 return "unaligned";
3889 break;
3890 case PRINT_ALIGNED:
3891 return "aligned";
3892 break;
3893 case PRINT_WRAPPED:
3894 return "wrapped";
3895 break;
3896 case PRINT_HTML:
3897 return "html";
3898 break;
3899 case PRINT_ASCIIDOC:
3900 return "asciidoc";
3901 break;
3902 case PRINT_LATEX:
3903 return "latex";
3904 break;
3905 case PRINT_LATEX_LONGTABLE:
3906 return "latex-longtable";
3907 break;
3908 case PRINT_TROFF_MS:
3909 return "troff-ms";
3910 break;
3911 }
3912 return "unknown";
3913 }
3914
3915 /*
3916 * Parse entered Unicode linestyle. If ok, update *linestyle and return
3917 * true, else return false.
3918 */
3919 static bool
set_unicode_line_style(const char * value,size_t vallen,unicode_linestyle * linestyle)3920 set_unicode_line_style(const char *value, size_t vallen,
3921 unicode_linestyle *linestyle)
3922 {
3923 if (pg_strncasecmp("single", value, vallen) == 0)
3924 *linestyle = UNICODE_LINESTYLE_SINGLE;
3925 else if (pg_strncasecmp("double", value, vallen) == 0)
3926 *linestyle = UNICODE_LINESTYLE_DOUBLE;
3927 else
3928 return false;
3929 return true;
3930 }
3931
3932 static const char *
_unicode_linestyle2string(int linestyle)3933 _unicode_linestyle2string(int linestyle)
3934 {
3935 switch (linestyle)
3936 {
3937 case UNICODE_LINESTYLE_SINGLE:
3938 return "single";
3939 break;
3940 case UNICODE_LINESTYLE_DOUBLE:
3941 return "double";
3942 break;
3943 }
3944 return "unknown";
3945 }
3946
3947 /*
3948 * do_pset
3949 *
3950 */
3951 bool
do_pset(const char * param,const char * value,printQueryOpt * popt,bool quiet)3952 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
3953 {
3954 size_t vallen = 0;
3955
3956 Assert(param != NULL);
3957
3958 if (value)
3959 vallen = strlen(value);
3960
3961 /* set format */
3962 if (strcmp(param, "format") == 0)
3963 {
3964 if (!value)
3965 ;
3966 else if (pg_strncasecmp("unaligned", value, vallen) == 0)
3967 popt->topt.format = PRINT_UNALIGNED;
3968 else if (pg_strncasecmp("aligned", value, vallen) == 0)
3969 popt->topt.format = PRINT_ALIGNED;
3970 else if (pg_strncasecmp("wrapped", value, vallen) == 0)
3971 popt->topt.format = PRINT_WRAPPED;
3972 else if (pg_strncasecmp("html", value, vallen) == 0)
3973 popt->topt.format = PRINT_HTML;
3974 else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
3975 popt->topt.format = PRINT_ASCIIDOC;
3976 else if (pg_strncasecmp("latex", value, vallen) == 0)
3977 popt->topt.format = PRINT_LATEX;
3978 else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
3979 popt->topt.format = PRINT_LATEX_LONGTABLE;
3980 else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
3981 popt->topt.format = PRINT_TROFF_MS;
3982 else
3983 {
3984 psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n");
3985 return false;
3986 }
3987 }
3988
3989 /* set table line style */
3990 else if (strcmp(param, "linestyle") == 0)
3991 {
3992 if (!value)
3993 ;
3994 else if (pg_strncasecmp("ascii", value, vallen) == 0)
3995 popt->topt.line_style = &pg_asciiformat;
3996 else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
3997 popt->topt.line_style = &pg_asciiformat_old;
3998 else if (pg_strncasecmp("unicode", value, vallen) == 0)
3999 popt->topt.line_style = &pg_utf8format;
4000 else
4001 {
4002 psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
4003 return false;
4004 }
4005 }
4006
4007 /* set unicode border line style */
4008 else if (strcmp(param, "unicode_border_linestyle") == 0)
4009 {
4010 if (!value)
4011 ;
4012 else if (set_unicode_line_style(value, vallen,
4013 &popt->topt.unicode_border_linestyle))
4014 refresh_utf8format(&(popt->topt));
4015 else
4016 {
4017 psql_error("\\pset: allowed Unicode border line styles are single, double\n");
4018 return false;
4019 }
4020 }
4021
4022 /* set unicode column line style */
4023 else if (strcmp(param, "unicode_column_linestyle") == 0)
4024 {
4025 if (!value)
4026 ;
4027 else if (set_unicode_line_style(value, vallen,
4028 &popt->topt.unicode_column_linestyle))
4029 refresh_utf8format(&(popt->topt));
4030 else
4031 {
4032 psql_error("\\pset: allowed Unicode column line styles are single, double\n");
4033 return false;
4034 }
4035 }
4036
4037 /* set unicode header line style */
4038 else if (strcmp(param, "unicode_header_linestyle") == 0)
4039 {
4040 if (!value)
4041 ;
4042 else if (set_unicode_line_style(value, vallen,
4043 &popt->topt.unicode_header_linestyle))
4044 refresh_utf8format(&(popt->topt));
4045 else
4046 {
4047 psql_error("\\pset: allowed Unicode header line styles are single, double\n");
4048 return false;
4049 }
4050 }
4051
4052 /* set border style/width */
4053 else if (strcmp(param, "border") == 0)
4054 {
4055 if (value)
4056 popt->topt.border = atoi(value);
4057 }
4058
4059 /* set expanded/vertical mode */
4060 else if (strcmp(param, "x") == 0 ||
4061 strcmp(param, "expanded") == 0 ||
4062 strcmp(param, "vertical") == 0)
4063 {
4064 if (value && pg_strcasecmp(value, "auto") == 0)
4065 popt->topt.expanded = 2;
4066 else if (value)
4067 {
4068 bool on_off;
4069
4070 if (ParseVariableBool(value, NULL, &on_off))
4071 popt->topt.expanded = on_off ? 1 : 0;
4072 else
4073 {
4074 PsqlVarEnumError(param, value, "on, off, auto");
4075 return false;
4076 }
4077 }
4078 else
4079 popt->topt.expanded = !popt->topt.expanded;
4080 }
4081
4082 /* locale-aware numeric output */
4083 else if (strcmp(param, "numericlocale") == 0)
4084 {
4085 if (value)
4086 return ParseVariableBool(value, param, &popt->topt.numericLocale);
4087 else
4088 popt->topt.numericLocale = !popt->topt.numericLocale;
4089 }
4090
4091 /* null display */
4092 else if (strcmp(param, "null") == 0)
4093 {
4094 if (value)
4095 {
4096 free(popt->nullPrint);
4097 popt->nullPrint = pg_strdup(value);
4098 }
4099 }
4100
4101 /* field separator for unaligned text */
4102 else if (strcmp(param, "fieldsep") == 0)
4103 {
4104 if (value)
4105 {
4106 free(popt->topt.fieldSep.separator);
4107 popt->topt.fieldSep.separator = pg_strdup(value);
4108 popt->topt.fieldSep.separator_zero = false;
4109 }
4110 }
4111
4112 else if (strcmp(param, "fieldsep_zero") == 0)
4113 {
4114 free(popt->topt.fieldSep.separator);
4115 popt->topt.fieldSep.separator = NULL;
4116 popt->topt.fieldSep.separator_zero = true;
4117 }
4118
4119 /* record separator for unaligned text */
4120 else if (strcmp(param, "recordsep") == 0)
4121 {
4122 if (value)
4123 {
4124 free(popt->topt.recordSep.separator);
4125 popt->topt.recordSep.separator = pg_strdup(value);
4126 popt->topt.recordSep.separator_zero = false;
4127 }
4128 }
4129
4130 else if (strcmp(param, "recordsep_zero") == 0)
4131 {
4132 free(popt->topt.recordSep.separator);
4133 popt->topt.recordSep.separator = NULL;
4134 popt->topt.recordSep.separator_zero = true;
4135 }
4136
4137 /* toggle between full and tuples-only format */
4138 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4139 {
4140 if (value)
4141 return ParseVariableBool(value, param, &popt->topt.tuples_only);
4142 else
4143 popt->topt.tuples_only = !popt->topt.tuples_only;
4144 }
4145
4146 /* set title override */
4147 else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4148 {
4149 free(popt->title);
4150 if (!value)
4151 popt->title = NULL;
4152 else
4153 popt->title = pg_strdup(value);
4154 }
4155
4156 /* set HTML table tag options */
4157 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4158 {
4159 free(popt->topt.tableAttr);
4160 if (!value)
4161 popt->topt.tableAttr = NULL;
4162 else
4163 popt->topt.tableAttr = pg_strdup(value);
4164 }
4165
4166 /* toggle use of pager */
4167 else if (strcmp(param, "pager") == 0)
4168 {
4169 if (value && pg_strcasecmp(value, "always") == 0)
4170 popt->topt.pager = 2;
4171 else if (value)
4172 {
4173 bool on_off;
4174
4175 if (!ParseVariableBool(value, NULL, &on_off))
4176 {
4177 PsqlVarEnumError(param, value, "on, off, always");
4178 return false;
4179 }
4180 popt->topt.pager = on_off ? 1 : 0;
4181 }
4182 else if (popt->topt.pager == 1)
4183 popt->topt.pager = 0;
4184 else
4185 popt->topt.pager = 1;
4186 }
4187
4188 /* set minimum lines for pager use */
4189 else if (strcmp(param, "pager_min_lines") == 0)
4190 {
4191 if (value)
4192 popt->topt.pager_min_lines = atoi(value);
4193 }
4194
4195 /* disable "(x rows)" footer */
4196 else if (strcmp(param, "footer") == 0)
4197 {
4198 if (value)
4199 return ParseVariableBool(value, param, &popt->topt.default_footer);
4200 else
4201 popt->topt.default_footer = !popt->topt.default_footer;
4202 }
4203
4204 /* set border style/width */
4205 else if (strcmp(param, "columns") == 0)
4206 {
4207 if (value)
4208 popt->topt.columns = atoi(value);
4209 }
4210 else
4211 {
4212 psql_error("\\pset: unknown option: %s\n", param);
4213 return false;
4214 }
4215
4216 if (!quiet)
4217 printPsetInfo(param, &pset.popt);
4218
4219 return true;
4220 }
4221
4222
4223 static bool
printPsetInfo(const char * param,struct printQueryOpt * popt)4224 printPsetInfo(const char *param, struct printQueryOpt *popt)
4225 {
4226 Assert(param != NULL);
4227
4228 /* show border style/width */
4229 if (strcmp(param, "border") == 0)
4230 printf(_("Border style is %d.\n"), popt->topt.border);
4231
4232 /* show the target width for the wrapped format */
4233 else if (strcmp(param, "columns") == 0)
4234 {
4235 if (!popt->topt.columns)
4236 printf(_("Target width is unset.\n"));
4237 else
4238 printf(_("Target width is %d.\n"), popt->topt.columns);
4239 }
4240
4241 /* show expanded/vertical mode */
4242 else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
4243 {
4244 if (popt->topt.expanded == 1)
4245 printf(_("Expanded display is on.\n"));
4246 else if (popt->topt.expanded == 2)
4247 printf(_("Expanded display is used automatically.\n"));
4248 else
4249 printf(_("Expanded display is off.\n"));
4250 }
4251
4252 /* show field separator for unaligned text */
4253 else if (strcmp(param, "fieldsep") == 0)
4254 {
4255 if (popt->topt.fieldSep.separator_zero)
4256 printf(_("Field separator is zero byte.\n"));
4257 else
4258 printf(_("Field separator is \"%s\".\n"),
4259 popt->topt.fieldSep.separator);
4260 }
4261
4262 else if (strcmp(param, "fieldsep_zero") == 0)
4263 {
4264 printf(_("Field separator is zero byte.\n"));
4265 }
4266
4267 /* show disable "(x rows)" footer */
4268 else if (strcmp(param, "footer") == 0)
4269 {
4270 if (popt->topt.default_footer)
4271 printf(_("Default footer is on.\n"));
4272 else
4273 printf(_("Default footer is off.\n"));
4274 }
4275
4276 /* show format */
4277 else if (strcmp(param, "format") == 0)
4278 {
4279 printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
4280 }
4281
4282 /* show table line style */
4283 else if (strcmp(param, "linestyle") == 0)
4284 {
4285 printf(_("Line style is %s.\n"),
4286 get_line_style(&popt->topt)->name);
4287 }
4288
4289 /* show null display */
4290 else if (strcmp(param, "null") == 0)
4291 {
4292 printf(_("Null display is \"%s\".\n"),
4293 popt->nullPrint ? popt->nullPrint : "");
4294 }
4295
4296 /* show locale-aware numeric output */
4297 else if (strcmp(param, "numericlocale") == 0)
4298 {
4299 if (popt->topt.numericLocale)
4300 printf(_("Locale-adjusted numeric output is on.\n"));
4301 else
4302 printf(_("Locale-adjusted numeric output is off.\n"));
4303 }
4304
4305 /* show toggle use of pager */
4306 else if (strcmp(param, "pager") == 0)
4307 {
4308 if (popt->topt.pager == 1)
4309 printf(_("Pager is used for long output.\n"));
4310 else if (popt->topt.pager == 2)
4311 printf(_("Pager is always used.\n"));
4312 else
4313 printf(_("Pager usage is off.\n"));
4314 }
4315
4316 /* show minimum lines for pager use */
4317 else if (strcmp(param, "pager_min_lines") == 0)
4318 {
4319 printf(ngettext("Pager won't be used for less than %d line.\n",
4320 "Pager won't be used for less than %d lines.\n",
4321 popt->topt.pager_min_lines),
4322 popt->topt.pager_min_lines);
4323 }
4324
4325 /* show record separator for unaligned text */
4326 else if (strcmp(param, "recordsep") == 0)
4327 {
4328 if (popt->topt.recordSep.separator_zero)
4329 printf(_("Record separator is zero byte.\n"));
4330 else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
4331 printf(_("Record separator is <newline>.\n"));
4332 else
4333 printf(_("Record separator is \"%s\".\n"),
4334 popt->topt.recordSep.separator);
4335 }
4336
4337 else if (strcmp(param, "recordsep_zero") == 0)
4338 {
4339 printf(_("Record separator is zero byte.\n"));
4340 }
4341
4342 /* show HTML table tag options */
4343 else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4344 {
4345 if (popt->topt.tableAttr)
4346 printf(_("Table attributes are \"%s\".\n"),
4347 popt->topt.tableAttr);
4348 else
4349 printf(_("Table attributes unset.\n"));
4350 }
4351
4352 /* show title override */
4353 else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4354 {
4355 if (popt->title)
4356 printf(_("Title is \"%s\".\n"), popt->title);
4357 else
4358 printf(_("Title is unset.\n"));
4359 }
4360
4361 /* show toggle between full and tuples-only format */
4362 else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4363 {
4364 if (popt->topt.tuples_only)
4365 printf(_("Tuples only is on.\n"));
4366 else
4367 printf(_("Tuples only is off.\n"));
4368 }
4369
4370 /* Unicode style formatting */
4371 else if (strcmp(param, "unicode_border_linestyle") == 0)
4372 {
4373 printf(_("Unicode border line style is \"%s\".\n"),
4374 _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4375 }
4376
4377 else if (strcmp(param, "unicode_column_linestyle") == 0)
4378 {
4379 printf(_("Unicode column line style is \"%s\".\n"),
4380 _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4381 }
4382
4383 else if (strcmp(param, "unicode_header_linestyle") == 0)
4384 {
4385 printf(_("Unicode header line style is \"%s\".\n"),
4386 _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4387 }
4388
4389 else
4390 {
4391 psql_error("\\pset: unknown option: %s\n", param);
4392 return false;
4393 }
4394
4395 return true;
4396 }
4397
4398
4399 static const char *
pset_bool_string(bool val)4400 pset_bool_string(bool val)
4401 {
4402 return val ? "on" : "off";
4403 }
4404
4405
4406 static char *
pset_quoted_string(const char * str)4407 pset_quoted_string(const char *str)
4408 {
4409 char *ret = pg_malloc(strlen(str) * 2 + 3);
4410 char *r = ret;
4411
4412 *r++ = '\'';
4413
4414 for (; *str; str++)
4415 {
4416 if (*str == '\n')
4417 {
4418 *r++ = '\\';
4419 *r++ = 'n';
4420 }
4421 else if (*str == '\'')
4422 {
4423 *r++ = '\\';
4424 *r++ = '\'';
4425 }
4426 else
4427 *r++ = *str;
4428 }
4429
4430 *r++ = '\'';
4431 *r = '\0';
4432
4433 return ret;
4434 }
4435
4436
4437 /*
4438 * Return a malloc'ed string for the \pset value.
4439 *
4440 * Note that for some string parameters, print.c distinguishes between unset
4441 * and empty string, but for others it doesn't. This function should produce
4442 * output that produces the correct setting when fed back into \pset.
4443 */
4444 static char *
pset_value_string(const char * param,struct printQueryOpt * popt)4445 pset_value_string(const char *param, struct printQueryOpt *popt)
4446 {
4447 Assert(param != NULL);
4448
4449 if (strcmp(param, "border") == 0)
4450 return psprintf("%d", popt->topt.border);
4451 else if (strcmp(param, "columns") == 0)
4452 return psprintf("%d", popt->topt.columns);
4453 else if (strcmp(param, "expanded") == 0)
4454 return pstrdup(popt->topt.expanded == 2
4455 ? "auto"
4456 : pset_bool_string(popt->topt.expanded));
4457 else if (strcmp(param, "fieldsep") == 0)
4458 return pset_quoted_string(popt->topt.fieldSep.separator
4459 ? popt->topt.fieldSep.separator
4460 : "");
4461 else if (strcmp(param, "fieldsep_zero") == 0)
4462 return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
4463 else if (strcmp(param, "footer") == 0)
4464 return pstrdup(pset_bool_string(popt->topt.default_footer));
4465 else if (strcmp(param, "format") == 0)
4466 return psprintf("%s", _align2string(popt->topt.format));
4467 else if (strcmp(param, "linestyle") == 0)
4468 return psprintf("%s", get_line_style(&popt->topt)->name);
4469 else if (strcmp(param, "null") == 0)
4470 return pset_quoted_string(popt->nullPrint
4471 ? popt->nullPrint
4472 : "");
4473 else if (strcmp(param, "numericlocale") == 0)
4474 return pstrdup(pset_bool_string(popt->topt.numericLocale));
4475 else if (strcmp(param, "pager") == 0)
4476 return psprintf("%d", popt->topt.pager);
4477 else if (strcmp(param, "pager_min_lines") == 0)
4478 return psprintf("%d", popt->topt.pager_min_lines);
4479 else if (strcmp(param, "recordsep") == 0)
4480 return pset_quoted_string(popt->topt.recordSep.separator
4481 ? popt->topt.recordSep.separator
4482 : "");
4483 else if (strcmp(param, "recordsep_zero") == 0)
4484 return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
4485 else if (strcmp(param, "tableattr") == 0)
4486 return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
4487 else if (strcmp(param, "title") == 0)
4488 return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
4489 else if (strcmp(param, "tuples_only") == 0)
4490 return pstrdup(pset_bool_string(popt->topt.tuples_only));
4491 else if (strcmp(param, "unicode_border_linestyle") == 0)
4492 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4493 else if (strcmp(param, "unicode_column_linestyle") == 0)
4494 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4495 else if (strcmp(param, "unicode_header_linestyle") == 0)
4496 return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4497 else
4498 return pstrdup("ERROR");
4499 }
4500
4501
4502
4503 #ifndef WIN32
4504 #define DEFAULT_SHELL "/bin/sh"
4505 #else
4506 /*
4507 * CMD.EXE is in different places in different Win32 releases so we
4508 * have to rely on the path to find it.
4509 */
4510 #define DEFAULT_SHELL "cmd.exe"
4511 #endif
4512
4513 static bool
do_shell(const char * command)4514 do_shell(const char *command)
4515 {
4516 int result;
4517
4518 if (!command)
4519 {
4520 char *sys;
4521 const char *shellName;
4522
4523 shellName = getenv("SHELL");
4524 #ifdef WIN32
4525 if (shellName == NULL)
4526 shellName = getenv("COMSPEC");
4527 #endif
4528 if (shellName == NULL)
4529 shellName = DEFAULT_SHELL;
4530
4531 /* See EDITOR handling comment for an explanation */
4532 #ifndef WIN32
4533 sys = psprintf("exec %s", shellName);
4534 #else
4535 sys = psprintf("\"%s\"", shellName);
4536 #endif
4537 result = system(sys);
4538 free(sys);
4539 }
4540 else
4541 result = system(command);
4542
4543 if (result == 127 || result == -1)
4544 {
4545 psql_error("\\!: failed\n");
4546 return false;
4547 }
4548 return true;
4549 }
4550
4551 /*
4552 * do_watch -- handler for \watch
4553 *
4554 * We break this out of exec_command to avoid having to plaster "volatile"
4555 * onto a bunch of exec_command's variables to silence stupider compilers.
4556 */
4557 static bool
do_watch(PQExpBuffer query_buf,double sleep)4558 do_watch(PQExpBuffer query_buf, double sleep)
4559 {
4560 long sleep_ms = (long) (sleep * 1000);
4561 printQueryOpt myopt = pset.popt;
4562 const char *strftime_fmt;
4563 const char *user_title;
4564 char *title;
4565 int title_len;
4566 int res = 0;
4567
4568 if (!query_buf || query_buf->len <= 0)
4569 {
4570 psql_error(_("\\watch cannot be used with an empty query\n"));
4571 return false;
4572 }
4573
4574 /*
4575 * Choose format for timestamps. We might eventually make this a \pset
4576 * option. In the meantime, using a variable for the format suppresses
4577 * overly-anal-retentive gcc warnings about %c being Y2K sensitive.
4578 */
4579 strftime_fmt = "%c";
4580
4581 /*
4582 * Set up rendering options, in particular, disable the pager, because
4583 * nobody wants to be prompted while watching the output of 'watch'.
4584 */
4585 myopt.topt.pager = 0;
4586
4587 /*
4588 * If there's a title in the user configuration, make sure we have room
4589 * for it in the title buffer. Allow 128 bytes for the timestamp plus 128
4590 * bytes for the rest.
4591 */
4592 user_title = myopt.title;
4593 title_len = (user_title ? strlen(user_title) : 0) + 256;
4594 title = pg_malloc(title_len);
4595
4596 for (;;)
4597 {
4598 time_t timer;
4599 char timebuf[128];
4600 long i;
4601
4602 /*
4603 * Prepare title for output. Note that we intentionally include a
4604 * newline at the end of the title; this is somewhat historical but it
4605 * makes for reasonably nicely formatted output in simple cases.
4606 */
4607 timer = time(NULL);
4608 strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
4609
4610 if (user_title)
4611 snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
4612 user_title, timebuf, sleep);
4613 else
4614 snprintf(title, title_len, _("%s (every %gs)\n"),
4615 timebuf, sleep);
4616 myopt.title = title;
4617
4618 /* Run the query and print out the results */
4619 res = PSQLexecWatch(query_buf->data, &myopt);
4620
4621 /*
4622 * PSQLexecWatch handles the case where we can no longer repeat the
4623 * query, and returns 0 or -1.
4624 */
4625 if (res <= 0)
4626 break;
4627
4628 /*
4629 * Set up cancellation of 'watch' via SIGINT. We redo this each time
4630 * through the loop since it's conceivable something inside
4631 * PSQLexecWatch could change sigint_interrupt_jmp.
4632 */
4633 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
4634 break;
4635
4636 /*
4637 * Enable 'watch' cancellations and wait a while before running the
4638 * query again. Break the sleep into short intervals (at most 1s)
4639 * since pg_usleep isn't interruptible on some platforms.
4640 */
4641 sigint_interrupt_enabled = true;
4642 i = sleep_ms;
4643 while (i > 0)
4644 {
4645 long s = Min(i, 1000L);
4646
4647 pg_usleep(s * 1000L);
4648 if (cancel_pressed)
4649 break;
4650 i -= s;
4651 }
4652 sigint_interrupt_enabled = false;
4653 }
4654
4655 pg_free(title);
4656 return (res >= 0);
4657 }
4658
4659 /*
4660 * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
4661 * returns true unless we have ECHO_HIDDEN_NOEXEC.
4662 */
4663 static bool
echo_hidden_command(const char * query)4664 echo_hidden_command(const char *query)
4665 {
4666 if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
4667 {
4668 printf(_("********* QUERY **********\n"
4669 "%s\n"
4670 "**************************\n\n"), query);
4671 fflush(stdout);
4672 if (pset.logfile)
4673 {
4674 fprintf(pset.logfile,
4675 _("********* QUERY **********\n"
4676 "%s\n"
4677 "**************************\n\n"), query);
4678 fflush(pset.logfile);
4679 }
4680
4681 if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
4682 return false;
4683 }
4684 return true;
4685 }
4686
4687 /*
4688 * Look up the object identified by obj_type and desc. If successful,
4689 * store its OID in *obj_oid and return TRUE, else return FALSE.
4690 *
4691 * Note that we'll fail if the object doesn't exist OR if there are multiple
4692 * matching candidates OR if there's something syntactically wrong with the
4693 * object description; unfortunately it can be hard to tell the difference.
4694 */
4695 static bool
lookup_object_oid(EditableObjectType obj_type,const char * desc,Oid * obj_oid)4696 lookup_object_oid(EditableObjectType obj_type, const char *desc,
4697 Oid *obj_oid)
4698 {
4699 bool result = true;
4700 PQExpBuffer query = createPQExpBuffer();
4701 PGresult *res;
4702
4703 switch (obj_type)
4704 {
4705 case EditableFunction:
4706
4707 /*
4708 * We have a function description, e.g. "x" or "x(int)". Issue a
4709 * query to retrieve the function's OID using a cast to regproc or
4710 * regprocedure (as appropriate).
4711 */
4712 appendPQExpBufferStr(query, "SELECT ");
4713 appendStringLiteralConn(query, desc, pset.db);
4714 appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
4715 strchr(desc, '(') ? "regprocedure" : "regproc");
4716 break;
4717
4718 case EditableView:
4719
4720 /*
4721 * Convert view name (possibly schema-qualified) to OID. Note:
4722 * this code doesn't check if the relation is actually a view.
4723 * We'll detect that in get_create_object_cmd().
4724 */
4725 appendPQExpBufferStr(query, "SELECT ");
4726 appendStringLiteralConn(query, desc, pset.db);
4727 appendPQExpBuffer(query, "::pg_catalog.regclass::pg_catalog.oid");
4728 break;
4729 }
4730
4731 if (!echo_hidden_command(query->data))
4732 {
4733 destroyPQExpBuffer(query);
4734 return false;
4735 }
4736 res = PQexec(pset.db, query->data);
4737 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
4738 *obj_oid = atooid(PQgetvalue(res, 0, 0));
4739 else
4740 {
4741 minimal_error_message(res);
4742 result = false;
4743 }
4744
4745 PQclear(res);
4746 destroyPQExpBuffer(query);
4747
4748 return result;
4749 }
4750
4751 /*
4752 * Construct a "CREATE OR REPLACE ..." command that describes the specified
4753 * database object. If successful, the result is stored in buf.
4754 */
4755 static bool
get_create_object_cmd(EditableObjectType obj_type,Oid oid,PQExpBuffer buf)4756 get_create_object_cmd(EditableObjectType obj_type, Oid oid,
4757 PQExpBuffer buf)
4758 {
4759 bool result = true;
4760 PQExpBuffer query = createPQExpBuffer();
4761 PGresult *res;
4762
4763 switch (obj_type)
4764 {
4765 case EditableFunction:
4766 printfPQExpBuffer(query,
4767 "SELECT pg_catalog.pg_get_functiondef(%u)",
4768 oid);
4769 break;
4770
4771 case EditableView:
4772
4773 /*
4774 * pg_get_viewdef() just prints the query, so we must prepend
4775 * CREATE for ourselves. We must fully qualify the view name to
4776 * ensure the right view gets replaced. Also, check relation kind
4777 * to be sure it's a view.
4778 *
4779 * Starting with 9.2, views may have reloptions (security_barrier)
4780 * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
4781 * CHECK OPTION. These are not part of the view definition
4782 * returned by pg_get_viewdef() and so need to be retrieved
4783 * separately. Materialized views (introduced in 9.3) may have
4784 * arbitrary storage parameter reloptions.
4785 */
4786 if (pset.sversion >= 90400)
4787 {
4788 printfPQExpBuffer(query,
4789 "SELECT nspname, relname, relkind, "
4790 "pg_catalog.pg_get_viewdef(c.oid, true), "
4791 "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4792 "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4793 "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
4794 "FROM pg_catalog.pg_class c "
4795 "LEFT JOIN pg_catalog.pg_namespace n "
4796 "ON c.relnamespace = n.oid WHERE c.oid = %u",
4797 oid);
4798 }
4799 else if (pset.sversion >= 90200)
4800 {
4801 printfPQExpBuffer(query,
4802 "SELECT nspname, relname, relkind, "
4803 "pg_catalog.pg_get_viewdef(c.oid, true), "
4804 "c.reloptions AS reloptions, "
4805 "NULL AS checkoption "
4806 "FROM pg_catalog.pg_class c "
4807 "LEFT JOIN pg_catalog.pg_namespace n "
4808 "ON c.relnamespace = n.oid WHERE c.oid = %u",
4809 oid);
4810 }
4811 else
4812 {
4813 printfPQExpBuffer(query,
4814 "SELECT nspname, relname, relkind, "
4815 "pg_catalog.pg_get_viewdef(c.oid, true), "
4816 "NULL AS reloptions, "
4817 "NULL AS checkoption "
4818 "FROM pg_catalog.pg_class c "
4819 "LEFT JOIN pg_catalog.pg_namespace n "
4820 "ON c.relnamespace = n.oid WHERE c.oid = %u",
4821 oid);
4822 }
4823 break;
4824 }
4825
4826 if (!echo_hidden_command(query->data))
4827 {
4828 destroyPQExpBuffer(query);
4829 return false;
4830 }
4831 res = PQexec(pset.db, query->data);
4832 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
4833 {
4834 resetPQExpBuffer(buf);
4835 switch (obj_type)
4836 {
4837 case EditableFunction:
4838 appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
4839 break;
4840
4841 case EditableView:
4842 {
4843 char *nspname = PQgetvalue(res, 0, 0);
4844 char *relname = PQgetvalue(res, 0, 1);
4845 char *relkind = PQgetvalue(res, 0, 2);
4846 char *viewdef = PQgetvalue(res, 0, 3);
4847 char *reloptions = PQgetvalue(res, 0, 4);
4848 char *checkoption = PQgetvalue(res, 0, 5);
4849
4850 /*
4851 * If the backend ever supports CREATE OR REPLACE
4852 * MATERIALIZED VIEW, allow that here; but as of today it
4853 * does not, so editing a matview definition in this way
4854 * is impossible.
4855 */
4856 switch (relkind[0])
4857 {
4858 #ifdef NOT_USED
4859 case RELKIND_MATVIEW:
4860 appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
4861 break;
4862 #endif
4863 case RELKIND_VIEW:
4864 appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
4865 break;
4866 default:
4867 psql_error("\"%s.%s\" is not a view\n",
4868 nspname, relname);
4869 result = false;
4870 break;
4871 }
4872 appendPQExpBuffer(buf, "%s.", fmtId(nspname));
4873 appendPQExpBufferStr(buf, fmtId(relname));
4874
4875 /* reloptions, if not an empty array "{}" */
4876 if (reloptions != NULL && strlen(reloptions) > 2)
4877 {
4878 appendPQExpBufferStr(buf, "\n WITH (");
4879 if (!appendReloptionsArray(buf, reloptions, "",
4880 pset.encoding,
4881 standard_strings()))
4882 {
4883 psql_error("could not parse reloptions array\n");
4884 result = false;
4885 }
4886 appendPQExpBufferStr(buf, ")");
4887 }
4888
4889 /* View definition from pg_get_viewdef (a SELECT query) */
4890 appendPQExpBuffer(buf, " AS\n%s", viewdef);
4891
4892 /* Get rid of the semicolon that pg_get_viewdef appends */
4893 if (buf->len > 0 && buf->data[buf->len - 1] == ';')
4894 buf->data[--(buf->len)] = '\0';
4895
4896 /* WITH [LOCAL|CASCADED] CHECK OPTION */
4897 if (checkoption && checkoption[0] != '\0')
4898 appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
4899 checkoption);
4900 }
4901 break;
4902 }
4903 /* Make sure result ends with a newline */
4904 if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
4905 appendPQExpBufferChar(buf, '\n');
4906 }
4907 else
4908 {
4909 minimal_error_message(res);
4910 result = false;
4911 }
4912
4913 PQclear(res);
4914 destroyPQExpBuffer(query);
4915
4916 return result;
4917 }
4918
4919 /*
4920 * If the given argument of \ef or \ev ends with a line number, delete the line
4921 * number from the argument string and return it as an integer. (We need
4922 * this kluge because we're too lazy to parse \ef's function or \ev's view
4923 * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
4924 *
4925 * Returns -1 if no line number is present, 0 on error, or a positive value
4926 * on success.
4927 */
4928 static int
strip_lineno_from_objdesc(char * obj)4929 strip_lineno_from_objdesc(char *obj)
4930 {
4931 char *c;
4932 int lineno;
4933
4934 if (!obj || obj[0] == '\0')
4935 return -1;
4936
4937 c = obj + strlen(obj) - 1;
4938
4939 /*
4940 * This business of parsing backwards is dangerous as can be in a
4941 * multibyte environment: there is no reason to believe that we are
4942 * looking at the first byte of a character, nor are we necessarily
4943 * working in a "safe" encoding. Fortunately the bitpatterns we are
4944 * looking for are unlikely to occur as non-first bytes, but beware of
4945 * trying to expand the set of cases that can be recognized. We must
4946 * guard the <ctype.h> macros by using isascii() first, too.
4947 */
4948
4949 /* skip trailing whitespace */
4950 while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
4951 c--;
4952
4953 /* must have a digit as last non-space char */
4954 if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
4955 return -1;
4956
4957 /* find start of digit string */
4958 while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
4959 c--;
4960
4961 /* digits must be separated from object name by space or closing paren */
4962 /* notice also that we are not allowing an empty object name ... */
4963 if (c == obj || !isascii((unsigned char) *c) ||
4964 !(isspace((unsigned char) *c) || *c == ')'))
4965 return -1;
4966
4967 /* parse digit string */
4968 c++;
4969 lineno = atoi(c);
4970 if (lineno < 1)
4971 {
4972 psql_error("invalid line number: %s\n", c);
4973 return 0;
4974 }
4975
4976 /* strip digit string from object name */
4977 *c = '\0';
4978
4979 return lineno;
4980 }
4981
4982 /*
4983 * Count number of lines in the buffer.
4984 * This is used to test if pager is needed or not.
4985 */
4986 static int
count_lines_in_buf(PQExpBuffer buf)4987 count_lines_in_buf(PQExpBuffer buf)
4988 {
4989 int lineno = 0;
4990 const char *lines = buf->data;
4991
4992 while (*lines != '\0')
4993 {
4994 lineno++;
4995 /* find start of next line */
4996 lines = strchr(lines, '\n');
4997 if (!lines)
4998 break;
4999 lines++;
5000 }
5001
5002 return lineno;
5003 }
5004
5005 /*
5006 * Write text at *lines to output with line numbers.
5007 *
5008 * If header_keyword isn't NULL, then line 1 should be the first line beginning
5009 * with header_keyword; lines before that are unnumbered.
5010 *
5011 * Caution: this scribbles on *lines.
5012 */
5013 static void
print_with_linenumbers(FILE * output,char * lines,const char * header_keyword)5014 print_with_linenumbers(FILE *output, char *lines,
5015 const char *header_keyword)
5016 {
5017 bool in_header = (header_keyword != NULL);
5018 size_t header_sz = in_header ? strlen(header_keyword) : 0;
5019 int lineno = 0;
5020
5021 while (*lines != '\0')
5022 {
5023 char *eol;
5024
5025 if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
5026 in_header = false;
5027
5028 /* increment lineno only for body's lines */
5029 if (!in_header)
5030 lineno++;
5031
5032 /* find and mark end of current line */
5033 eol = strchr(lines, '\n');
5034 if (eol != NULL)
5035 *eol = '\0';
5036
5037 /* show current line as appropriate */
5038 if (in_header)
5039 fprintf(output, " %s\n", lines);
5040 else
5041 fprintf(output, "%-7d %s\n", lineno, lines);
5042
5043 /* advance to next line, if any */
5044 if (eol == NULL)
5045 break;
5046 lines = ++eol;
5047 }
5048 }
5049
5050 /*
5051 * Report just the primary error; this is to avoid cluttering the output
5052 * with, for instance, a redisplay of the internally generated query
5053 */
5054 static void
minimal_error_message(PGresult * res)5055 minimal_error_message(PGresult *res)
5056 {
5057 PQExpBuffer msg;
5058 const char *fld;
5059
5060 msg = createPQExpBuffer();
5061
5062 fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
5063 if (fld)
5064 printfPQExpBuffer(msg, "%s: ", fld);
5065 else
5066 printfPQExpBuffer(msg, "ERROR: ");
5067 fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
5068 if (fld)
5069 appendPQExpBufferStr(msg, fld);
5070 else
5071 appendPQExpBufferStr(msg, "(not available)");
5072 appendPQExpBufferStr(msg, "\n");
5073
5074 psql_error("%s", msg->data);
5075
5076 destroyPQExpBuffer(msg);
5077 }
5078