📄 gqlplus.c
字号:
/* Module name: gqlplus.c Created by: Ljubomir J. Buturovic Created: May 18, 2002 Purpose: drop-in replacement for sqlplus with command line editing/history and table/column name completion. Copyright (C) 2004 Ljubomir J. Buturovic. All Rights Reserved.*//* This file implements a command-line program 'gqlplus', a drop-in replacement for Oracle SQL utility sqlplus. The intention is to provide as much as possible of the sqlplus functionality, with the addition of command-line editing, history and table/column name completion, similar to tcsh and bash shells. To achieve this, the program uses GNU Readline Library. The program is licensed under the GNU General Public License. To compile: % cc -D_REENTRANT gqlplus.c -o gqlplus -lreadline -lcurses Readline must be installed on your system.*//* * Modification Log. * * $Log: gqlplus.c,v $ * Revision 1.191 2006/12/02 08:34:42 ljubomir * Use EDITOR environment variable to define the editor. * * Revision 1.190 2006/10/04 04:16:29 ljubomir * Add ORACLE_PATH (contributed by Grant Hollingworth). * * Revision 1.189 2006/08/06 01:49:34 ljubomir * Reorder command-line options in the Usage message. * * Revision 1.188 2006/08/01 06:57:36 ljubomir * Kill sqlplus using SIGTERM. * * Revision 1.187 2006/07/20 05:39:29 ljubomir * *** empty log message *** * * Revision 1.186 2006/07/17 01:23:16 ljubomir * Introduce const_correctness. * * Revision 1.185 2006/07/16 07:53:17 ljubomir * Update usage() for -p switch. * * Revision 1.184 2006/07/16 07:50:21 ljubomir * Optionally support progress report and elapsed time information * (contributed by Mark Harrison of Pixar). * * Revision 1.183 2006/07/15 00:03:38 ljubomir * Add environment variable NLS_DATE_FORMAT. Contributed by Yen-Ming Lee. * * Revision 1.182 2006/03/28 20:10:13 ljubomir * Define the debugging function print_environment(). * * Revision 1.181 2006/03/27 18:56:59 ljubomir * Add DYLD_LIBRARY_PATH environment variable (the Mac OSX version of LD_LIBRARY_PATH). * * Revision 1.180 2006/01/30 06:45:22 ljubomir * Handle, to some extent, the prompt-less ACCEPT command. * * Revision 1.179 2006/01/30 06:24:12 ljubomir * Add a sleep(1) in accept_sql(), to guarantee entire sqlplus message * arrives in a single read(). * * Revision 1.178 2006/01/29 08:41:31 ljubomir * Attempt to handle sqlplus errors in accept_cmd(). * * Revision 1.177 2006/01/29 01:54:09 ljubomir * Finally correctly implement ACCEPT command (however with prompt). * * Revision 1.176 2006/01/27 08:15:39 ljubomir * Move towards implementing the ACCEPT command. * * Revision 1.175 2006/01/25 05:56:35 ljubomir * 1.12 * * Revision 1.174 2006/01/25 05:39:12 ljubomir * Fix terrible memory violation in file_set_editor(). * * Revision 1.173 2006/01/22 06:52:21 ljubomir * Correct rescanning after CONNECT command. * * Revision 1.172 2006/01/22 04:22:48 ljubomir * Move installation of completion until after the CONNECT command has been sent * to sqlplus (that's the only way it makes sense). * * Revision 1.171 2006/01/22 03:48:47 ljubomir * Completion after reconnect doesn't work... strange error SP2-0029. * * Revision 1.170 2006/01/22 03:22:47 ljubomir * Reinstall completion names after each connect. * * Revision 1.169 2006/01/22 03:04:52 ljubomir * Remove all references to the useless SIGCHLD handling... it does not solve the abnormal sqlplus * termination problem, because it cannot distinguish between abnormal and normal termination. * Instead, we exit if write() to sqlplus fails. * * Revision 1.168 2006/01/22 03:02:08 ljubomir * Solve the sqlplus termination problem... * * Revision 1.167 2006/01/22 02:53:29 ljubomir * Prepare to handle Broken pipe (sqlplus terminated). * * Revision 1.166 2006/01/22 01:51:11 ljubomir * Close the reading end of parent-to-child pipe in the parent. * * Revision 1.165 2006/01/21 19:46:16 ljubomir * Terminate futile efforts to handle SIGCHLD. * * Revision 1.164 2006/01/21 19:14:00 ljubomir * More attempts at SIGCHLD handling. Still disabled, though. * * Revision 1.163 2006/01/21 15:27:59 ljubomir * Add comment. * * Revision 1.162 2006/01/21 15:21:56 ljubomir * Use kill_sqlplus(). * * Revision 1.161 2006/01/21 15:02:53 ljubomir * Prepare to handle SIGCHLD. * * Revision 1.160 2006/01/20 07:41:41 ljubomir * Prepare to handle SIGCHLD. * * Revision 1.159 2006/01/20 07:15:28 ljubomir * *** empty log message *** * * Revision 1.158 2005/12/08 01:03:29 ljubomir * Initialize `pstat' in main(). Caused /nolog to fail. * * Revision 1.157 2005/07/01 05:51:36 ljubomir * Properly check mode searching for an executable. * * Revision 1.156 2005/07/01 04:55:01 ljubomir * Add logging code. Initialize variables in get_completion_names(). * * Revision 1.155 2005/06/25 21:02:54 ljubomir * Disable tablename completion in we are unable to query or parse ALL_TABLES/ALL_VIEWS. * * Revision 1.154 2005/06/25 20:40:03 ljubomir * Robustify get_names() and get_column_names(). * * Revision 1.153 2005/06/24 05:30:35 ljubomir * Set NLS_COMP and NLS_SORT environment variables. * Don't crash in get_names() if table owner is not defined (not sure * if this can happen, but just in case). * * Revision 1.152 2005/06/23 01:56:47 ljubomir * Version 1.11. * * Revision 1.151 2005/06/23 01:54:30 ljubomir * Optionally print sqlplus binary. * * Revision 1.150 2005/05/22 08:09:57 ljubomir * Use sfree() to simplify code. * * Revision 1.149 2005/05/22 05:31:28 ljubomir * Finish support for user-defined prompt combined with time. * * Revision 1.148 2005/05/21 22:18:03 ljubomir * Correctly handle `set time on' in the presence of user-defined SQL prompt. * * Revision 1.147 2005/05/21 19:48:40 ljubomir * Implement and comment the new rules for finding sqlplus executable: ${PATH}, * followed by ${ORACLE_HOME}/bin, followed by ./sqlplus. * * Revision 1.146 2005/05/21 07:46:46 ljubomir * Prevent various crashes. Do not continue in get_sql_prompt() if system() fails. * * Revision 1.145 2005/05/21 05:25:31 ljubomir * Fix get_connect_string() in case password has the net service name. * * Revision 1.144 2005/05/20 03:22:39 ljubomir * Remove strtok_r(). * * Revision 1.143 2005/05/19 07:12:39 ljubomir * Remove libgen.h - not needed? * * Revision 1.142 2005/05/19 06:20:01 ljubomir * Correct behavior in case of /nolog command-line argument. * * Revision 1.141 2005/05/16 01:13:13 ljubomir * Remove unused variables. * * Revision 1.140 2005/05/16 01:11:24 ljubomir * Intermediate revision. Support Oracle instantclient - no longer require ORACLE_HOME. * * Revision 1.139 2005/05/11 01:31:29 ljubomir * Fix endless loop in file_set_editor() (contributed by Jeff Mital). * * Revision 1.138 2005/05/11 00:46:11 ljubomir * Version 1.10. * * Revision 1.137 2004/06/29 06:24:29 ljubomir * Increase usleep() period in get_final_sqlplus(). * * Revision 1.136 2004/06/29 06:02:34 ljubomir * Add Copyright statement. At exit, print the last remaining output from sqlplus. * * Revision 1.135 2004/06/29 02:11:01 ljubomir * Do not hang if QUIT command is issued in disconnected state. * * Revision 1.134 2004/06/23 05:34:03 ljubomir * Do not crash looking for glogin.sql. * * Revision 1.133 2004/06/21 07:53:34 ljubomir * Increase space for path. * * Revision 1.132 2004/06/21 00:19:57 ljubomir * Use DISPLAY environment variable for Emacs editor, do not hardcode the display. * * Revision 1.131 2004/06/20 23:40:07 ljubomir * Finally implement the correct rules for extracting editor informatio from * glogin.sql/login.sql files. Also, open Emacs in a separate window. * * Revision 1.130 2004/06/17 16:52:22 ljubomir * Fix crash when SET command given without arguments. * * Revision 1.129 2004/06/17 15:32:19 ljubomir * Do not crash in PAUSE command if the prompt is the default. * * Revision 1.128 2004/06/17 15:02:53 ljubomir * Support ACCEPT command. * * Revision 1.127 2004/06/17 03:05:34 ljubomir * Correctly handle numeric prompt when SET TIME ON is in effect. * Reported by Josh Trutwin. * * Revision 1.126 2004/06/16 17:16:01 ljubomir * Add handling of RECOVER_PROMPT, contributed by Eniac Zhang. * * Revision 1.125 2004/05/20 06:02:40 ljubomir * When looking for _define for editor, search local login.sql followed by * ${HOME}/login.sql. * * Revision 1.124 2004/05/19 08:55:02 ljubomir * Fix parsing of login.sql. * * Revision 1.123 2003/11/05 19:19:45 ljubomir * Add the TWO_TASK environment variable. Contributed by * Mladen Gogala. * * Revision 1.122 2003/10/29 06:28:46 ljubomir * Correctly get table names (for completion) if pagesize is set to 0. * * Revision 1.121 2003/10/23 19:03:26 ljubomir * Adjust to properly handle read() semantics on Linux, in pause_cmd(). * * Revision 1.120 2003/10/23 18:15:22 ljubomir * Fix handling of CONNECT/DISCONNECT commands. * * Revision 1.119 2003/10/22 23:16:32 ljubomir * VERSION 1.8. * * Revision 1.118 2003/10/22 21:52:07 ljubomir * Finish - hopefully - implementing PAUSE, SET PAUSE. * * Revision 1.117 2003/10/22 21:39:08 ljubomir * Better implementation of PAUSE and SET PAUSE. * * Revision 1.116 2003/10/22 21:03:56 ljubomir * Attempt to implement the 'set pause on' command. Not very good yet. * * Revision 1.115 2003/10/20 23:22:13 ljubomir * Clean-up warning according to Jos Backus suggestions. * * Revision 1.114 2003/10/20 22:44:08 ljubomir * Beautify 'host' command - add the trailing newline. * * Revision 1.113 2003/10/19 00:43:40 ljubomir * Bug fix: do not lowercase arguments to HOST command. * * Revision 1.112 2003/10/19 00:35:24 ljubomir * Fix bug: shell launched whenever string 'ho' appears within a multi-line sqlplus command. * * Revision 1.111 2003/10/19 00:18:49 ljubomir * Support filename argument for 'edit' command. * * Revision 1.110 2003/10/18 23:47:31 ljubomir * Pause command actually takes three characters to be distinguished. * * Revision 1.109 2003/10/18 23:46:15 ljubomir * Finish the 'pause' command support. * * Revision 1.108 2003/10/18 19:54:49 ljubomir * First attempt to support PAUSE command. Imperfect, but at least it doesn't hang. * * Revision 1.107 2003/10/17 16:29:55 ljubomir * Attempt to fix the double-Ctrl-C problem - fix doesn't work, disabled for now. * * Revision 1.106 2003/05/06 17:08:02 ljubomir * Incorporate bug fix from Steven Kehlet: gqlplus crashes if invoked like gqlplus "/ as sysdba" * and the database is closed. * * Revision 1.105 2003/03/25 21:49:42 ljubomir * Final beautification, usage(). * * Revision 1.104 2003/03/25 17:58:35 ljubomir * Improve column name handling. Beautify usage(). * * Revision 1.103 2003/03/25 17:06:08 ljubomir * Set history to 200, beautify usage() message. * * Revision 1.102 2003/03/24 14:33:29 ljubomir * Make sure USAGE_PROMPT is more specific. * * Revision 1.101 2003/03/24 01:02:57 ljubomir * Report gqlplus version. * * Revision 1.100 2003/03/24 00:38:00 ljubomir * Initialize history. * * Revision 1.99 2003/03/24 00:21:07 ljubomir * Make sure passwords do not end up in history. * * Revision 1.98 2003/03/24 00:12:27 ljubomir * Beautify usage(); re-enable echo after password command. * * Revision 1.97 2003/03/24 00:01:21 ljubomir * Complete 'password' command handling. * * Revision 1.96 2003/03/23 23:57:42 ljubomir * Add 'password' command handling. * * Revision 1.95 2003/03/23 22:56:06 ljubomir * Add gqlplus-specific usage message. * * Revision 1.94 2003/03/23 06:37:17 ljubomir * Synchronize with CVS version. * * Revision 1.6 2003/02/23 23:16:01 ljubomir * Untabify. * * Revision 1.5 2003/02/22 22:30:40 zhewu * change comment style from java/c++ * * Revision 1.4 2003/02/22 22:23:02 zhewu * one more change for completion when first connected. * * Revision 1.3 2003/02/22 17:37:32 zhewu * Add fix for haning problem when use gqlplus inside ADE version control * system. * Add command history handling and rebuild table/view name completion * after connect to a different schema. * */static char rcsid[] = "$Id: gqlplus.c,v 1.191 2006/12/02 08:34:42 ljubomir Exp $";#include <unistd.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <stdio.h>#include <sys/types.h>#include <signal.h>#include <fcntl.h>#include <termios.h>#include <sys/wait.h>#include <errno.h>#include <sys/stat.h>#include <readline/readline.h>#include <readline/history.h>#if !defined(MAXPATHLEN)# define MAXPATHLEN 512#endif#define VERSION "1.12"#define INIT_LENGTH 10#define MAX_LINE_LENGTH 100000#define INIT_LINE_LENGTH 100#define BUF_LEN 1000#define MAX_PROMPT_LEN 100000 /* hard to believe anyone would want a longer prompt */#define NPROMPT 1#define INIT_NUM_TABLES 50#define INIT_NUM_COLUMNS 50#define MAX_NARGS 100#define MAX_NENV 50#define SQL_PROMPT "SQL> "#define USER_PROMPT "Enter user-name: "#define PASSWORD_PROMPT "Enter password: "#define OLD_PASSWORD "Old password: "#define NEW_PASSWORD "New password: "#define RETYPE_PASSWORD "Retype new password: "#define QUIT_PROMPT_1 "Disconnected from Oracle"#define QUIT_PROMPT_2 "unable to CONNECT to ORACLE"#define USAGE_PROMPT "Usage: SQLPLUS"#define VALUE_PROMPT "Enter value for "#define RECOVER_PROMPT "Specify log: {<RET>=suggested | filename | AUTO | CANCEL}"#define SQLPROMPT "sqlprompt"#define SQLEXT ".sql"#define LIST_CMD "list\n"#define DEL_CMD "del 1 LAST\n"#define EDIT_CMD "ed"#define CLEAR_CMD "cl"#define SCREEN "scr"#define WHITESPACE " \t"#define DIGITS "0123456789"#define HOST_CMD "ho"#define DEFINE_CMD "define"#define SET_CMD "set"#define SQLPROMPT_CMD "sqlprompt"#define PAUSE_CMD "pause"#define SELECT_CMD "select"#define CONNECT_CMD "connect"#define DISCONNECT_CMD "disconnect"#define QUIT_CMD "quit"#define ON_CMD "on"#define PAGESIZE_CMD "show pagesize\n"#define ACCEPT_CMD "accept"#define GET_PROMPT "echo \"show sqlprompt;\" | "#define TAIL_PROMPT ""#define SELECT_TABLES_1 "select distinct table_name, owner from all_tables where owner != 'SYS' union "#define SELECT_TABLES_2 "select distinct view_name, owner from all_views where owner != 'SYS';\n"#define DESCRIBE "describe"#define VI_EDITOR "/bin/vi"#define EDITOR "_editor"#define AFIEDT "afiedt.buf"#define NO_LINES "No lines in SQL buffer.\n"#define NOTHING_TO_SAVE "Nothing to save.\n"#define AFIEDT_ERRMSG "Cannot create save file \"afiedt.buf\"\n"#define ORACLE_HOME "ORACLE_HOME"#define ORACLE_SID "ORACLE_SID"#define SQLPATH "SQLPATH"#define TNS_ADMIN "TNS_ADMIN"#define TWO_TASK "TWO_TASK" /* Added by M. Gogala, 11/5/2003 */#define NLS_LANG "NLS_LANG" /* Added by dbakorea */#define ORA_NLS33 "ORA_NLS33" /* Added by dbakorea */#define NLS_DATE_FORMAT "NLS_DATE_FORMAT" /* Added by leeym */#define NLS_COMP "NLS_COMP" #define NLS_SORT "NLS_SORT" #define LD_LIBRARY_PATH "LD_LIBRARY_PATH" #define DYLD_LIBRARY_PATH "DYLD_LIBRARY_PATH" #define ORACLE_PATH "ORACLE_PATH" /* contributed by Grant Hollingworth */#define PATH "PATH"#define TERM "TERM"#define SPACETAB " \t"#define STARTUP 1#define CONNECTED 2#define DISCONNECTED 3static int fds1[2];static int fds2[2];static int pipe_size;static int state;static int progress; /* display progress report/elapsed time information */ /* functionality contributed by Mark Harrison of Pixar */static char *_editor;static pid_t sqlplus_pid;static pid_t edit_pid;static int quit_sqlplus = 0;static int complete_columns = 1; /* if 0, don't do column name completion */struct sigaction iact;struct sigaction qact;struct sigaction cact;struct sigaction pact;static FILE *lptr;static char *sql_prompt = (char *) 0; /* user-defined prompt */static char *username = (char *) 0;static char* szCmdPrefix = "--!";static char *histname;static int histmax = 200;void save_history(void){ if (history_list() == NULL) /* If history is of length 0 (because set as is or slave is not executable) */ unlink(histname); else { write_history(histname); chmod(histname, 0600); }}void initialize_history(char *appl_name){ char buffer[MAXPATHLEN]; /* Find the real name of the history file using the tilde_expand function * which is in the readline library. */ sprintf(buffer, "~/.%s_history", appl_name); histname = tilde_expand(buffer); using_history(); if (histmax >= 0) { stifle_history(histmax); atexit(save_history); read_history(histname); } else { max_input_history = -histmax; }}/* Remove leading and trailing spaces from str.*/static char *trim(char *str)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -