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