/*-------------------------------------------------------------------------
*
* psql.c--
- * an interactive front-end to postgres95
+ * an interactive front-end to postgreSQL
*
* Copyright (c) 1996, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.32 1996/11/22 06:45:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.58 1997/03/12 21:19:14 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
+#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include "postgres.h"
#include "libpq-fe.h"
+#include "pqsignal.h"
#include "stringutils.h"
-
#include "psqlHelp.h"
-
-#ifdef NOREADLINE
-#include "rlstubs.h"
-#else
-/* from the GNU readline library */
-#ifdef OLD_READLINE
-#include "readline.h"
-#include "history.h"
-#else
-#include <readline/readline.h>
-#include <readline/history.h>
+#ifndef HAVE_STRDUP
+#include "strdup.h"
#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
#endif
+#ifdef HAVE_LIBREADLINE
+# ifdef HAVE_READLINE_H
+# include <readline.h>
+# if defined(HAVE_HISTORY) || defined(HAVE_LIBHISTORY)
+# include <history.h>
+# endif
+# else
+# include <readline/readline.h>
+# if defined(HAVE_HISTORY) || defined(HAVE_LIBHISTORY)
+# include <readline/history.h>
+# endif
+# endif
+#endif
+
+#define PROMPT "=> "
+
#define MAX_QUERY_BUFFER 20000
#define COPYBUFSIZ 8192
bool singleStep; /* prompt before for each query */
bool singleLineMode; /* query terminated by newline */
bool useReadline;/* use libreadline routines */
+ bool getPassword;/* prompt the user for a username and password */
} PsqlSettings;
/* declarations for functions in this file */
FILE * copystream);
static int tableList(PsqlSettings * ps, bool deep_tablelist);
static int tableDesc(PsqlSettings * ps, char *table);
+static void prompt_for_password(char *username, char *password);
+static char * make_connect_string(char *host, char *port, char *dbname,
+ char *username, char *password);
char *gets_noreadline(char *prompt, FILE * source);
char *gets_readline(char *prompt, FILE * source);
fprintf(stderr, "\t -s single step mode (prompts for each query)\n");
fprintf(stderr, "\t -S single line mode (i.e. query terminated by newline)\n");
fprintf(stderr, "\t -t turn off printing of headings and row count\n");
+ fprintf(stderr, "\t -u ask for a username and password for authentication\n");
fprintf(stderr, "\t -T html set html3.0 table command options (cf. -H)\n");
fprintf(stderr, "\t -x turn on expanded output (field names on left)\n");
exit(1);
fprintf(stderr, " \\a -- toggle field-alignment (currenty %s)\n", on(ps->opt.align));
fprintf(stderr, " \\C [<captn>] -- set html3 caption (currently '%s')\n", ps->opt.caption ? ps->opt.caption : "");
fprintf(stderr, " \\connect <dbname> -- connect to new database (currently '%s')\n", PQdb(ps->db));
- fprintf(stderr, " \\copy <dbname> -- copy table to/from a file\n");
+ fprintf(stderr, " \\copy table {from | to} <fname>\n");
fprintf(stderr, " \\d [<table>] -- list tables in database or columns in <table>, * for all\n");
fprintf(stderr, " \\e [<fname>] -- edit the current query buffer or <fname>, \\E execute too\n");
fprintf(stderr, " \\f [<sep>] -- change field separater (currently '%s')\n", ps->opt.fieldSep);
char *
gets_readline(char *prompt, FILE * source)
{
- return (readline(prompt));
+ char *s;
+#ifdef HAVE_LIBREADLINE
+ s = readline(prompt);
+#else
+ char buf[500];
+ printf("%s", prompt);
+ s = fgets(buf, 500, stdin);
+#endif
+ fputc('\r', stdout);
+ fflush(stdout);
+ return s;
}
/*
break;
case PGRES_COPY_IN:
*success_p = true;
- if (copy_in) {
+ if (copy_in)
handleCopyIn(results, false, copystream);
- } else {
- char c;
- /*
- * eat extra newline still in input buffer
- *
- */
- fflush(stdin);
- if ((c = getc(stdin)) != '\n' && c != EOF)
- (void) ungetc(c, stdin);
+ else
handleCopyIn(results, !settings->quiet, stdin);
- }
break;
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
} else {
copystream = fopen(file, "w");
}
- if (copystream < 0)
+ if (copystream == NULL)
fprintf(stderr,
"Unable to open file %s which to copy, errno = %s (%d).",
from ? "from" : "to", strerror(errno), errno);
PQfinish(olddb);
free(settings->prompt);
settings->prompt = malloc(strlen(PQdb(settings->db)) + 10);
- sprintf(settings->prompt, "%s=> ", PQdb(settings->db));
+ sprintf(settings->prompt, "%s%s", PQdb(settings->db), PROMPT);
}
}
}
char *fs = DEFAULT_FIELD_SEP;
if (optarg)
fs = optarg;
- if (settings->opt.fieldSep);
+ if (settings->opt.fieldSep)
free(settings->opt.fieldSep);
if (!(settings->opt.fieldSep = strdup(fs))) {
perror("malloc");
case 's': /* \s is save history to a file */
if (!optarg)
optarg = "/dev/tty";
+#ifdef HAVE_HISTORY
if (write_history(optarg) != 0)
fprintf(stderr, "cannot write history to %s\n", optarg);
+#endif
break;
case 'm': /* monitor like type-setting */
if (toggle(settings, &settings->opt.standard, "standard SQL separaters and padding")) {
char *query_start;
interactive = ((source == stdin) && !settings->notty);
-#define PROMPT "=> "
if (interactive) {
if (settings->prompt)
free(settings->prompt);
else
sprintf(settings->prompt, "%s%s", PQdb(settings->db), PROMPT);
if (settings->useReadline) {
+#ifdef HAVE_HISTORY
using_history();
+#endif
GetNextLine = gets_readline;
} else
GetNextLine = gets_noreadline;
/* main loop for getting queries and executing them */
while (!eof) {
if (slashCmdStatus == 3) {
+ paren_level = 0;
line = strdup(query);
query[0] = '\0';
} else {
+ if (interactive && !settings->quiet) {
+ if (in_quote)
+ settings->prompt[strlen(settings->prompt)-3] = '\'';
+ else if (query[0] != '\0' && !querySent)
+ settings->prompt[strlen(settings->prompt)-3] = '-';
+ else
+ settings->prompt[strlen(settings->prompt)-3] = '=';
+ }
line = GetNextLine(settings->prompt, source);
+#ifdef HAVE_HISTORY
if (interactive && settings->useReadline && line != NULL)
add_history(line); /* save non-empty lines in history */
+#endif
}
query_start = line;
if (line == NULL) { /* No more input. Time to quit */
- printf("EOF\n"); /* Goes on prompt line */
+ if (!settings->quiet)
+ printf("EOF\n"); /* Goes on prompt line */
eof = true;
} else {
- if (!interactive && !settings->singleStep && !settings->quiet)
- fprintf(stderr, "%s\n", line);
-
/* remove whitespaces on the right, incl. \n's */
line = rightTrim(line);
+ if (!interactive && !settings->singleStep && !settings->quiet)
+ fprintf(stderr, "%s\n", line);
+
if (line[0] == '\0') {
free(line);
continue;
query_start,
query);
if (slashCmdStatus == 1) {
+ if (query[0] == '\0')
+ paren_level = 0;
free(line);
continue;
}
settings.opt.pager = 1;
if (!isatty(0) || !isatty(1))
settings.quiet = settings.notty = 1;
-#ifndef NOREADLINE
+#ifdef HAVE_LIBREADLINE
else
settings.useReadline = 1;
#endif
+#ifdef PSQL_ALWAYS_GET_PASSWORDS
+ settings.getPassword = 1;
+#else
+ settings.getPassword = 0;
+#endif
- while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:x")) != EOF) {
+ while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lh:Hnso:p:qStT:ux")) != EOF) {
switch (c) {
case 'A':
settings.opt.align = 0;
case 'T':
settings.opt.tableOpt = optarg;
break;
+ case 'u':
+ settings.getPassword = 1;
+ break;
case 'x':
settings.opt.expanded = 1;
break;
if (listDatabases)
dbname = "template1";
- settings.db = PQsetdb(host, port, NULL, NULL, dbname);
+ if(settings.getPassword) {
+ char username[9];
+ char password[9];
+ char *connect_string;
+
+ prompt_for_password(username, password);
+
+ /* now use PQconnectdb so we can pass these options */
+ connect_string = make_connect_string(host, port, dbname, username, password);
+ settings.db = PQconnectdb(connect_string);
+ free(connect_string);
+ } else {
+ settings.db = PQsetdb(host, port, NULL, NULL, dbname);
+ }
+
dbname = PQdb(settings.db);
if (PQstatus(settings.db) == CONNECTION_BAD) {
exit(listAllDbs(&settings));
}
if (!settings.quiet && !singleQuery && !qfilename) {
- printf("Welcome to the POSTGRES95 interactive sql monitor:\n");
+ printf("Welcome to the POSTGRESQL interactive sql monitor:\n");
printf(" Please read the file COPYRIGHT for copyright terms "
- "of POSTGRES95\n\n");
+ "of POSTGRESQL\n\n");
printf(" type \\? for help on slash commands\n");
printf(" type \\q to quit\n");
printf(" type \\g or terminate with semicolon to execute query\n");
else
fclose(ps->queryFout);
}
- if (!fname)
+ if (!fname) {
ps->queryFout = stdout;
+ pqsignal(SIGPIPE, SIG_DFL);
+ }
else {
if (*fname == '|') {
- signal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, SIG_IGN);
ps->queryFout = popen(fname + 1, "w");
ps->pipe = 1;
} else {
ps->queryFout = fopen(fname, "w");
+ pqsignal(SIGPIPE, SIG_DFL);
ps->pipe = 0;
}
if (!ps->queryFout) {
}
return ps->queryFout;
}
+
+static void prompt_for_password(char *username, char *password)
+{
+ int length;
+#ifdef HAVE_TERMIOS_H
+ struct termios t_orig, t;
+#endif
+
+ printf("Username: ");
+ fgets(username, 9, stdin);
+ length = strlen(username);
+ if(length > 0 && username[length-1] == '\n') username[length-1] = '\0';
+
+ printf("Password: ");
+#ifdef HAVE_TERMIOS_H
+ tcgetattr(0, &t);
+ t_orig = t;
+ t.c_lflag &= ~ECHO;
+ tcsetattr(0, TCSADRAIN, &t);
+#endif
+ fgets(password, 9, stdin);
+#ifdef HAVE_TERMIOS_H
+ tcsetattr(0, TCSADRAIN, &t_orig);
+#endif
+
+ length = strlen(password);
+ if(length > 0 && password[length-1] == '\n') password[length-1] = '\0';
+
+ printf("\n\n");
+}
+
+static char *make_connect_string(char *host, char *port, char *dbname,
+ char *username, char *password)
+{
+ int connect_string_len = 0;
+ char *connect_string;
+
+ if(host)
+ connect_string_len += 6 + strlen(host); /* 6 == "host=" + " " */
+ if(username)
+ connect_string_len += 6 + strlen(username); /* 6 == "user=" + " " */
+ if(password)
+ connect_string_len += 10 + strlen(password); /* 10 == "password=" + " " */
+ if(port)
+ connect_string_len += 6 + strlen(port); /* 6 == "port=" + " " */
+ if(dbname)
+ connect_string_len += 8 + strlen(dbname); /* 8 == "dbname=" + " " */
+ connect_string_len += 18; /* "authtype=password" + null */
+
+ connect_string = (char *)malloc(connect_string_len);
+ if(!connect_string) {
+ return 0;
+ }
+ connect_string[0] = '\0';
+ if(host) {
+ strcat(connect_string, "host=");
+ strcat(connect_string, host);
+ strcat(connect_string, " ");
+ }
+ if(username) {
+ strcat(connect_string, "user=");
+ strcat(connect_string, username);
+ strcat(connect_string, " ");
+ }
+ if(password) {
+ strcat(connect_string, "password=");
+ strcat(connect_string, password);
+ strcat(connect_string, " ");
+ }
+ if(port) {
+ strcat(connect_string, "port=");
+ strcat(connect_string, port);
+ strcat(connect_string, " ");
+ }
+ if(dbname) {
+ strcat(connect_string, "dbname=");
+ strcat(connect_string, dbname);
+ strcat(connect_string, " ");
+ }
+ strcat(connect_string, "authtype=password");
+
+ return connect_string;
+}
+