📄 command.c
字号:
const char *dbparam = NULL; const char *userparam = NULL; const char *pwparam = NULL; char *prompted_password = NULL; bool need_pass; bool success = false; /* Delete variables (in case we fail before setting them anew) */ UnsyncVariables(); /* If dbname is "" then use old name, else new one (even if NULL) */ if (oldconn && new_dbname && PQdb(oldconn) && strcmp(new_dbname, "") == 0) dbparam = PQdb(oldconn); else dbparam = new_dbname; /* If user is "" then use the old one */ if (new_user && PQuser(oldconn) && strcmp(new_user, "") == 0) userparam = PQuser(oldconn); else userparam = new_user; /* need to prompt for password? */ if (pset.getPassword) pwparam = prompted_password = simple_prompt("Password: ", 100, false); /* * Use old password (if any) if no new one given and we are * reconnecting as same user */ if (!pwparam && oldconn && PQuser(oldconn) && userparam && strcmp(PQuser(oldconn), userparam) == 0) pwparam = PQpass(oldconn); do { need_pass = false; pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn), NULL, NULL, dbparam, userparam, pwparam); if (PQstatus(pset.db) == CONNECTION_BAD && strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0 && !feof(stdin)) { PQfinish(pset.db); need_pass = true; free(prompted_password); prompted_password = NULL; pwparam = prompted_password = simple_prompt("Password: ", 100, false); } } while (need_pass); free(prompted_password); /* * If connection failed, try at least keep the old one. That's * probably more convenient than just kicking you out of the program. */ if (!pset.db || PQstatus(pset.db) == CONNECTION_BAD) { if (pset.cur_cmd_interactive) { psql_error("%s", PQerrorMessage(pset.db)); PQfinish(pset.db); if (oldconn) { fputs(gettext("Previous connection kept\n"), stderr); pset.db = oldconn; } else pset.db = NULL; } else { /* * we don't want unpredictable things to happen in scripting * mode */ psql_error("\\connect: %s", PQerrorMessage(pset.db)); PQfinish(pset.db); if (oldconn) PQfinish(oldconn); pset.db = NULL; } } else { if (!QUIET()) { if (userparam != new_user) /* no new user */ printf(gettext("You are now connected to database \"%s\".\n"), dbparam); else if (dbparam != new_dbname) /* no new db */ printf(gettext("You are now connected as new user \"%s\".\n"), new_user); else/* both new */ printf(gettext("You are now connected to database \"%s\" as user \"%s\".\n"), PQdb(pset.db), PQuser(pset.db)); } if (oldconn) PQfinish(oldconn); success = true; } PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); /* Update variables */ SyncVariables(); return success;}/* * SyncVariables * * Make psql's internal variables agree with connection state upon * establishing a new connection. */voidSyncVariables(void){ /* get stuff from connection */ pset.encoding = PQclientEncoding(pset.db); pset.popt.topt.encoding = pset.encoding; SetVariable(pset.vars, "DBNAME", PQdb(pset.db)); SetVariable(pset.vars, "USER", PQuser(pset.db)); SetVariable(pset.vars, "HOST", PQhost(pset.db)); SetVariable(pset.vars, "PORT", PQport(pset.db)); SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); /* send stuff to it, too */ SyncVerbosityVariable();}/* * UnsyncVariables * * Clear variables that should be not be set when there is no connection. */voidUnsyncVariables(void){ SetVariable(pset.vars, "DBNAME", NULL); SetVariable(pset.vars, "USER", NULL); SetVariable(pset.vars, "HOST", NULL); SetVariable(pset.vars, "PORT", NULL); SetVariable(pset.vars, "ENCODING", NULL);}/* * Update connection state from VERBOSITY variable */voidSyncVerbosityVariable(void){ switch (SwitchVariable(pset.vars, "VERBOSITY", "default", "terse", "verbose", NULL)) { case 1: /* default */ PQsetErrorVerbosity(pset.db, PQERRORS_DEFAULT); break; case 2: /* terse */ PQsetErrorVerbosity(pset.db, PQERRORS_TERSE); break; case 3: /* verbose */ PQsetErrorVerbosity(pset.db, PQERRORS_VERBOSE); break; default: /* not set or unrecognized value */ PQsetErrorVerbosity(pset.db, PQERRORS_DEFAULT); break; }}/* * do_edit -- handler for \e * * If you do not specify a filename, the current query buffer will be copied * into a temporary one. */static booleditFile(const char *fname){ const char *editorName; char *sys; int result;#ifdef USE_ASSERT_CHECKING assert(fname);#else if (!fname) return false;#endif /* Find an editor to use */ editorName = getenv("PSQL_EDITOR"); if (!editorName) editorName = getenv("EDITOR"); if (!editorName) editorName = getenv("VISUAL"); if (!editorName) editorName = DEFAULT_EDITOR; sys = malloc(strlen(editorName) + strlen(fname) + 10 + 1); if (!sys) return false; sprintf(sys,#ifndef WIN32 "exec "#endif "%s '%s'", editorName, fname); result = system(sys); if (result == -1) psql_error("could not start editor \"%s\"\n", editorName); else if (result == 127) psql_error("could not start /bin/sh\n"); free(sys); return result == 0;}/* call this one */static booldo_edit(const char *filename_arg, PQExpBuffer query_buf){ char fnametmp[MAXPGPATH]; FILE *stream = NULL; const char *fname; bool error = false; int fd;#ifndef WIN32 struct stat before, after;#endif if (filename_arg) fname = filename_arg; else { /* make a temp file to edit */#ifndef WIN32 const char *tmpdirenv = getenv("TMPDIR"); snprintf(fnametmp, sizeof(fnametmp), "%s/psql.edit.%ld.%ld", tmpdirenv ? tmpdirenv : "/tmp", (long) geteuid(), (long) getpid());#else GetTempFileName(".", "psql", 0, fnametmp);#endif fname = (const char *) fnametmp; fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd != -1) stream = fdopen(fd, "w"); if (fd == -1 || !stream) { psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno)); error = true; } else { unsigned int ql = query_buf->len; if (ql == 0 || query_buf->data[ql - 1] != '\n') { appendPQExpBufferChar(query_buf, '\n'); ql++; } if (fwrite(query_buf->data, 1, ql, stream) != ql) { psql_error("%s: %s\n", fname, strerror(errno)); fclose(stream); remove(fname); error = true; } else fclose(stream); } }#ifndef WIN32 if (!error && stat(fname, &before) != 0) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; }#endif /* call editor */ if (!error) error = !editFile(fname);#ifndef WIN32 if (!error && stat(fname, &after) != 0) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } if (!error && before.st_mtime != after.st_mtime) {#else if (!error) {#endif stream = fopen(fname, "r"); if (!stream) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } else { /* read file back in */ char line[1024]; resetPQExpBuffer(query_buf); while (fgets(line, sizeof(line), stream) != NULL) appendPQExpBufferStr(query_buf, line); if (ferror(stream)) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; }#ifdef USE_READLINE#ifdef HAVE_REPLACE_HISTORY_ENTRY replace_history_entry(where_history(), query_buf->data, NULL);#else add_history(query_buf->data);#endif#endif fclose(stream); } } /* remove temp file */ if (!filename_arg) { if (remove(fname) == -1) { psql_error("%s: %s\n", fname, strerror(errno)); error = true; } } return !error;}/* * process_file * * Read commands from filename and then them to the main processing loop * Handler for \i, but can be used for other things as well. */intprocess_file(char *filename){ FILE *fd; int result; char *oldfilename; if (!filename) return false; fd = fopen(filename, "r"); if (!fd) { psql_error("%s: %s\n", filename, strerror(errno)); return false; } oldfilename = pset.inputfile; pset.inputfile = filename; result = MainLoop(fd); fclose(fd); pset.inputfile = oldfilename; return result;}/* * do_pset * */static const char *_align2string(enum printFormat in){ switch (in) { case PRINT_NOTHING: return "nothing"; break; case PRINT_UNALIGNED: return "unaligned"; break; case PRINT_ALIGNED: return "aligned"; break; case PRINT_HTML: return "html"; break; case PRINT_LATEX: return "latex"; break; } return "unknown";}booldo_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet){ size_t vallen = 0;#ifdef USE_ASSERT_CHECKING assert(param);#else if (!param) return false;#endif if (value) vallen = strlen(value); /* set format */ if (strcmp(param, "format") == 0) { if (!value) ; else if (strncasecmp("unaligned", value, vallen) == 0) popt->topt.format = PRINT_UNALIGNED; else if (strncasecmp("aligned", value, vallen) == 0) popt->topt.format = PRINT_ALIGNED; else if (strncasecmp("html", value, vallen) == 0) popt->topt.format = PRINT_HTML; else if (strncasecmp("latex", value, vallen) == 0) popt->topt.format = PRINT_LATEX; else { psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n"); return false; } if (!quiet) printf(gettext("Output format is %s.\n"), _align2string(popt->topt.format)); } /* set border style/width */ else if (strcmp(param, "border") == 0) { if (value) popt->topt.border = atoi(value); if (!quiet) printf(gettext("Border style is %d.\n"), popt->topt.border); } /* set expanded/vertical mode */ else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0) { popt->topt.expanded = !popt->topt.expanded; if (!quiet) printf(popt->topt.expanded ? gettext("Expanded display is on.\n") : gettext("Expanded display is off.\n")); } /* null display */ else if (strcmp(param, "null") == 0) { if (value) { free(popt->nullPrint); popt->nullPrint = xstrdup(value); } if (!quiet) printf(gettext("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : ""); } /* field separator for unaligned text */ else if (strcmp(param, "fieldsep") == 0) { if (value) { free(popt->topt.fieldSep); popt->topt.fieldSep = xstrdup(value); } if (!quiet) printf(gettext("Field separator is \"%s\".\n"), popt->topt.fieldSep); } /* record separator for unaligned text */ else if (strcmp(param, "recordsep") == 0) { if (value) { free(popt->topt.recordSep); popt->topt.recordSep = xstrdup(value); } if (!quiet) { if (strcmp(popt->topt.recordSep, "\n") == 0) printf(gettext("Record separator is <newline>.")); else printf(gettext("Record separator is \"%s\".\n"), popt->topt.recordSep); } } /* toggle between full and barebones format */ else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0) { popt->topt.tuples_only = !popt->topt.tuples_only; if (!quiet) { if (popt->topt.tuples_only) puts(gettext("Showing only tuples.")); else puts(gettext("Tuples only is off.")); } } /* set title override */ else if (strcmp(param, "title") == 0) { free(popt->title); if (!value) popt->title = NULL; else popt->title = xstrdup(value); if (!quiet) { if (popt->title) printf(gettext("Title is \"%s\".\n"), popt->title); else printf(gettext("Title is unset.\n")); } } /* set HTML table tag options */ else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0) { free(popt->topt.tableAttr); if (!value) popt->topt.tableAttr = NULL; else popt->topt.tableAttr = xstrdup(value); if (!quiet) { if (popt->topt.tableAttr) printf(gettext("Table attribute is \"%s\".\n"), popt->topt.tableAttr); else printf(gettext("Table attributes unset.\n")); } } /* toggle use of pager */ else if (strcmp(param, "pager") == 0) { if (value && strcasecmp(value, "always") == 0) popt->topt.pager = 2; else if (popt->topt.pager == 1) popt->topt.pager = 0; else popt->topt.pager = 1; if (!quiet) { if (popt->topt.pager == 1) puts(gettext("Pager is used for long output.")); else if (popt->topt.pager == 2) puts(gettext("Pager is always used.")); else puts(gettext("Pager usage is off.")); } } /* disable "(x rows)" footer */ else if (strcmp(param, "footer") == 0) { popt->default_footer = !popt->default_footer; if (!quiet) { if (popt->default_footer) puts(gettext("Default footer is on.")); else puts(gettext("Default footer is off.")); } } else { psql_error("\\pset: unknown option: %s\n", param); return false; } return true;}#define DEFAULT_SHELL "/bin/sh"static booldo_shell(const char *command){ int result; if (!command) { char *sys; const char *shellName; shellName = getenv("SHELL"); if (shellName == NULL) shellName = DEFAULT_SHELL; sys = malloc(strlen(shellName) + 16); if (!sys) { psql_error("out of memory\n"); if (pset.cur_cmd_interactive) return false; else exit(EXIT_FAILURE); } sprintf(sys,#ifndef WIN32 "exec "#endif "%s", shellName); result = system(sys); free(sys); } else result = system(command); if (result == 127 || result == -1) { psql_error("\\!: failed\n"); return false; } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -