diff options
author | mwesdorp <mwesdorp> | 2013-04-25 14:09:47 +0000 |
---|---|---|
committer | mwesdorp <mwesdorp> | 2013-04-25 14:09:47 +0000 |
commit | ed5fdf742a5039576bc581a335fa9494a760000c (patch) | |
tree | 7f56ad436e424aebc16167a65e81e84a8096c798 /src | |
parent | 4b49cc67ac8d7654b88ded70baa0109d8d162cde (diff) |
sqsh-2.2.0 new features and bugfixes
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd_connect.c | 325 | ||||
-rw-r--r-- | src/cmd_input.c | 242 | ||||
-rw-r--r-- | src/cmd_reconnect.c | 14 | ||||
-rw-r--r-- | src/sqsh_debug.h | 1 | ||||
-rw-r--r-- | src/sqsh_env.c | 97 | ||||
-rw-r--r-- | src/sqsh_env.h | 3 | ||||
-rw-r--r-- | src/sqsh_expand.c | 43 | ||||
-rw-r--r-- | src/sqsh_history.c | 9 | ||||
-rw-r--r-- | src/sqsh_init.c | 13 | ||||
-rw-r--r-- | src/sqsh_main.c | 48 | ||||
-rw-r--r-- | src/var.h | 10 | ||||
-rw-r--r-- | src/var_debug.c | 3 |
12 files changed, 510 insertions, 298 deletions
diff --git a/src/cmd_connect.c b/src/cmd_connect.c index 2820e7d..8cc7888 100644 --- a/src/cmd_connect.c +++ b/src/cmd_connect.c @@ -24,8 +24,10 @@ */ #include <stdio.h> #include <ctype.h> +#include <setjmp.h> #include <ctpublic.h> #include "sqsh_config.h" +#include "sqsh_debug.h" #include "sqsh_error.h" #include "sqsh_global.h" #include "sqsh_getopt.h" @@ -40,7 +42,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_connect.c,v 1.28 2013/04/18 11:54:43 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: cmd_connect.c,v 1.29 2013/04/25 14:09:47 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -109,7 +111,9 @@ static CS_RETCODE ShowNetAuthCredExp _ANSI_ARGS((CS_CONNECTION *, ; /* sqsh-2.2.0 - Signal handler to respond to SIGINT during cmd_connect */ -static void connect_signal ( int, void *); +static JMP_BUF sg_jmp_buf; +static int sg_interrupted; +static void connect_run_sigint ( int, void *); /* * cmd_connect: @@ -186,6 +190,9 @@ int cmd_connect( argc, argv ) CS_INT SybTimeOut; CS_BOOL NetAuthRequired; varbuf_t *exp_buf = NULL; + /* sqsh-2.2.0 - New variables */ + char *debug_tds_logdata; + char *debug_tds_capture; #if defined(CTLIB_SIGPOLL_BUG) && defined(F_SETOWN) int ctlib_fd; @@ -257,14 +264,15 @@ int cmd_connect( argc, argv ) } break ; case 'N' : /* sqsh-2.1.5 */ - if (env_put( g_env, "appname", sqsh_optarg, ENV_F_TRAN ) == False) - { + if (env_put( g_env, "appname", sqsh_optarg, ENV_F_TRAN ) == False) + { fprintf( stderr, "\\connect: -N: %s\n", sqsh_get_errstr() ); - have_error = True; - } + have_error = True; + } break; case 'P' : - if (g_password_set == True && g_password != NULL) strcpy( orig_password, g_password ); + if (g_password_set == True && g_password != NULL) + strcpy( orig_password, g_password ); password_changed = True; if (env_put( g_env, "password", sqsh_optarg, ENV_F_TRAN ) == False) @@ -405,12 +413,15 @@ int cmd_connect( argc, argv ) sqsh_exit( 255 ); } - /* - * sqsh-2.2.0 - Install a signal handler to catch SIGINT during cmd_connect. - * The current signals are saved first and restored at the end of cmd_connect. - */ + /* + * sqsh-2.2.0 - Install a signal handler to catch SIGINT during cmd_connect. + * The current signals are saved first and restored at the end of cmd_connect. + */ sig_save(); - sig_install( SIGINT, connect_signal, (void *) NULL, 0); + sig_install( SIGINT, connect_run_sigint, (void *) NULL, 0); + sg_interrupted = False; + if (SETJMP( sg_jmp_buf ) != 0) + goto connect_fail; /* * If the $session variable is set and the path that it contains @@ -617,19 +628,19 @@ int cmd_connect( argc, argv ) goto connect_fail; if (ct_callback( g_context, /* Context */ - (CS_CONNECTION*)NULL, /* Connection */ - CS_SET, /* Action */ - CS_CLIENTMSG_CB, /* Type */ - (CS_VOID*)syb_client_cb /* Callback Pointer */ - ) != CS_SUCCEED) + (CS_CONNECTION*)NULL, /* Connection */ + CS_SET, /* Action */ + CS_CLIENTMSG_CB, /* Type */ + (CS_VOID*)syb_client_cb /* Callback Pointer */ + ) != CS_SUCCEED) goto connect_fail; if (ct_callback( g_context, /* Context */ - (CS_CONNECTION*)NULL, /* Connection */ - CS_SET, /* Action */ - CS_SERVERMSG_CB, /* Type */ - (CS_VOID*)syb_server_cb /* Callback Pointer */ - ) != CS_SUCCEED) + (CS_CONNECTION*)NULL, /* Connection */ + CS_SET, /* Action */ + CS_SERVERMSG_CB, /* Type */ + (CS_VOID*)syb_server_cb /* Callback Pointer */ + ) != CS_SUCCEED) goto connect_fail; /* @@ -639,12 +650,12 @@ int cmd_connect( argc, argv ) #if !defined(_WINDOZE_) netio_type = CS_SYNC_IO; if (ct_config( g_context, /* Context */ - CS_SET, /* Action */ - CS_NETIO, /* Property */ - (CS_VOID*)&netio_type, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SET, /* Action */ + CS_NETIO, /* Property */ + (CS_VOID*)&netio_type, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; #endif @@ -705,7 +716,7 @@ int cmd_connect( argc, argv ) (CS_VOID*)cp, /* Buffer */ CS_NULLTERM, /* Buffer Length */ NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) goto connect_fail; } else @@ -826,12 +837,12 @@ int cmd_connect( argc, argv ) if (hostname != NULL && *hostname != '\0') { if (ct_con_props( g_connection, /* Connection */ - CS_SET, /* Action */ - CS_HOSTNAME, /* Property */ - (CS_VOID*)hostname, /* Buffer */ - CS_NULLTERM, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SET, /* Action */ + CS_HOSTNAME, /* Property */ + (CS_VOID*)hostname, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; } @@ -840,12 +851,12 @@ int cmd_connect( argc, argv ) { i = atoi(packet_size); if (ct_con_props( g_connection, /* Connection */ - CS_SET, /* Action */ - CS_PACKETSIZE, /* Property */ - (CS_VOID*)&i, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SET, /* Action */ + CS_PACKETSIZE, /* Property */ + (CS_VOID*)&i, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; } @@ -854,12 +865,12 @@ int cmd_connect( argc, argv ) { i = CS_TRUE; if (ct_con_props( g_connection, /* Connection */ - CS_SET, /* Action */ - CS_SEC_ENCRYPTION, /* Property */ - (CS_VOID*)&i, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SET, /* Action */ + CS_SEC_ENCRYPTION, /* Property */ + (CS_VOID*)&i, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; #if defined (CS_SEC_EXTENDED_ENCRYPTION) @@ -868,13 +879,13 @@ int cmd_connect( argc, argv ) * connect to ASE servers with 'net password encryption reqd' * configured to 2 (RSA). */ - if (ct_con_props( g_connection, /* Connection */ - CS_SET, /* Action */ - CS_SEC_EXTENDED_ENCRYPTION, /* Property */ - (CS_VOID*)&i, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + if (ct_con_props( g_connection, /* Connection */ + CS_SET, /* Action */ + CS_SEC_EXTENDED_ENCRYPTION, /* Property */ + (CS_VOID*)&i, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; #endif @@ -891,50 +902,50 @@ int cmd_connect( argc, argv ) /*-- Initialize --*/ if (cs_locale( g_context, /* Context */ CS_SET, /* Action */ - locale, /* Locale Structure */ + locale, /* Locale Structure */ CS_LC_ALL, /* Property */ - (CS_CHAR*)NULL, /* Buffer */ + (CS_CHAR*)NULL, /* Buffer */ CS_UNUSED, /* Buffer Length */ (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) goto connect_fail; /*-- Language --*/ if( language != NULL && *language != '\0' ) { - if (cs_locale( g_context, /* Context */ - CS_SET, /* Action */ - locale, /* Locale Structure */ - CS_SYB_LANG, /* Property */ - (CS_CHAR*)language, /* Buffer */ - CS_NULLTERM, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + if (cs_locale( g_context, /* Context */ + CS_SET, /* Action */ + locale, /* Locale Structure */ + CS_SYB_LANG, /* Property */ + (CS_CHAR*)language, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; } /*-- Character Set --*/ - if (charset != NULL && *charset != '\0') /* sqsh-2.1.6 sanity check */ + if (charset != NULL && *charset != '\0') /* sqsh-2.1.6 sanity check */ { - if (cs_locale( g_context, /* Context */ - CS_SET, /* Action */ - locale, /* Locale Structure */ - CS_SYB_CHARSET, /* Property */ - (CS_CHAR*)charset, /* Buffer */ - CS_NULLTERM, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + if (cs_locale( g_context, /* Context */ + CS_SET, /* Action */ + locale, /* Locale Structure */ + CS_SYB_CHARSET, /* Property */ + (CS_CHAR*)charset, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; } /*-- Locale Property --*/ - if (ct_con_props( g_connection, /* Connection */ - CS_SET, /* Action */ - CS_LOC_PROP, /* Property */ - (CS_VOID*)locale, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + if (ct_con_props( g_connection, /* Connection */ + CS_SET, /* Action */ + CS_LOC_PROP, /* Property */ + (CS_VOID*)locale, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) goto connect_fail; /* Handle case where server is defined as host:port */ @@ -956,6 +967,97 @@ int cmd_connect( argc, argv ) } #endif +#if defined (DEBUG) && defined (CS_SET_DBG_FILE) && defined (CS_SET_PROTOCOL_FILE) + /* + * sqsh-2.2.0 - Setup TDS debugging using a logdata file and or a capture file + * for tracing TDS packets. + */ + if ( sqsh_debug_show (DEBUG_TDS) ) + { + /* + * Note, this requires the CT-lib development libraries to be linked/loaded with sqsh. + */ + env_get (g_env, "debug_tds_logdata", &debug_tds_logdata); + if (debug_tds_logdata != NULL && *debug_tds_logdata != '\0') + { + if (sqsh_expand( debug_tds_logdata, exp_buf, 0 ) != False) + { + cp = varbuf_getstr( exp_buf ); + if (ct_debug ( g_context, /* Context */ + NULL, /* Connection */ + CS_SET_DBG_FILE, /* Action */ + CS_UNUSED, /* Flag */ + cp, /* Buffer value */ + strlen(cp) /* Buffer length */ + ) != CS_SUCCEED) + fprintf (stderr, "\\connect: ct_debug - Unable to set CS_SET_DBG_FILE to %s\n", cp); + else + { + fprintf (stdout, "\\connect: ct_debug - Successfully set CS_SET_DBG_FILE to %s\n", cp); + if (ct_debug ( g_context, /* Context */ + g_connection, /* Connection */ + CS_SET_FLAG, /* Action */ + CS_DBG_ALL, /* Flag */ + NULL, /* Buffer value */ + CS_UNUSED /* Buffer length */ + ) != CS_SUCCEED) + fprintf (stderr, "\\connect: ct_debug - Unable to set flag CS_DBG_ALL\n"); + else + fprintf (stdout, "\\connect: ct_debug - Flag CS_DBG_ALL successfully set\n"); + } + } + else + { + fprintf( stderr, "sqsh: Error expanding $debug_tds_logdata: %s\n", sqsh_get_errstr() ); + } + } + + /* + * For protocol tracing regular CT-lib libraries will do. + * The created trace file can be decoded using Ribo. + */ + env_get (g_env, "debug_tds_capture", &debug_tds_capture); + if (debug_tds_capture != NULL && *debug_tds_capture != '\0') + { + if (sqsh_expand( debug_tds_capture, exp_buf, 0 ) != False) + { + cp = varbuf_getstr( exp_buf ); + if (ct_debug ( NULL, /* Context */ + g_connection, /* Connection */ + CS_SET_PROTOCOL_FILE, /* Action */ + CS_UNUSED, /* Flag */ + cp, /* Buffer value */ + strlen(cp) /* Buffer length */ + ) != CS_SUCCEED) + fprintf (stderr, "\\connect: ct_debug - Unable to set CS_SET_PROTOCOL_FILE to %s\n", cp); + else + { + fprintf (stdout, "\\connect: ct_debug - Successfully set CS_SET_PROTOCOL_FILE to %s\n", cp); + if (ct_debug ( NULL, /* Context */ + g_connection, /* Connection */ + CS_SET_FLAG, /* Action */ + CS_DBG_PROTOCOL, /* Flag */ + NULL, /* Buffer value */ + CS_UNUSED /* Buffer length */ + ) != CS_SUCCEED) + fprintf (stderr, "\\connect: ct_debug - Unable to set falg CS_DBG_PROTOCOL\n"); + else + fprintf (stdout, "\\connect: ct_debug - Flag CS_DBG_PROTOCOL successfully set\n"); + } + } + else + { + fprintf( stderr, "sqsh: Error expanding $debug_tds_capture: %s\n", sqsh_get_errstr() ); + } + } + } +#elif defined (DEBUG) + if ( sqsh_debug_show (DEBUG_TDS) ) + { + fprintf( stderr, "\\connect: ct_debug - TDS debugging is not supported in this version of CT-lib\n" ); + } +#endif + /* * We sit in a loop and attempt to connect while we are getting * "Login failed" messages. @@ -1026,12 +1128,12 @@ int cmd_connect( argc, argv ) * that CT-Lib uses a file descriptor as its communication mechanism. */ if (ct_con_props( g_connection, /* Connection */ - CS_GET, /* Action */ - CS_ENDPOINT, /* Property */ - (CS_VOID*)&ctlib_fd, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_GET, /* Action */ + CS_ENDPOINT, /* Property */ + (CS_VOID*)&ctlib_fd, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) { fprintf( stderr, "\\connect: WARNING: Unable to fetch CT-Lib file\n" ); fprintf( stderr, "\\connect: descriptor to work around SIGPOLL bug.\n" ); @@ -1071,7 +1173,8 @@ int cmd_connect( argc, argv ) CS_TDS_VERSION, /* Property */ (CS_VOID*)&version, /* Buffer */ CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL ) == CS_SUCCEED) + (CS_INT*)NULL + ) == CS_SUCCEED) { switch (version) { case CS_TDS_40: @@ -1196,16 +1299,16 @@ connect_fail: } /*-- Clean up the connection if established --*/ - if (g_connection != NULL) + if (g_connection != NULL && sg_interrupted == False) { - /*-- Find out if the we are connected or not --*/ if (ct_con_props( g_connection, /* Connection */ CS_GET, /* Action */ CS_CON_STATUS, /* Property */ (CS_VOID*)&con_status, /* Buffer */ CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL ) != CS_SUCCEED) + (CS_INT*)NULL + ) != CS_SUCCEED) { DBG(sqsh_debug(DEBUG_ERROR, "connect: Unable to get con status.\n");) con_status = CS_CONSTAT_CONNECTED; @@ -1228,20 +1331,22 @@ connect_fail: ct_con_drop( g_connection ); } - if (locale != NULL) + if (sg_interrupted == False) { - DBG(sqsh_debug(DEBUG_ERROR, "connect: Dropping locale\n");) - cs_loc_drop( g_context, locale ); - } + if (locale != NULL) + { + DBG(sqsh_debug(DEBUG_ERROR, "connect: Dropping locale\n");) + cs_loc_drop( g_context, locale ); + } - if (g_context != NULL) - { - DBG(sqsh_debug(DEBUG_ERROR, "connect: Dropping context\n");) - if (ct_exit( g_context, CS_UNUSED ) != CS_SUCCEED) - ct_exit( g_context, CS_FORCE_EXIT ); - cs_ctx_drop( g_context ); + if (g_context != NULL) + { + DBG(sqsh_debug(DEBUG_ERROR, "connect: Dropping context\n");) + if (ct_exit( g_context, CS_UNUSED ) != CS_SUCCEED) + ct_exit( g_context, CS_FORCE_EXIT ); + cs_ctx_drop( g_context ); + } } - g_connection = NULL; g_context = NULL; return_code = CMD_FAIL; @@ -1594,13 +1699,15 @@ static CS_RETCODE syb_client_cb ( ctx, con, msg ) if (sg_login == False) { env_get( g_env, "DSQUERY", &server ) ; - /* +#if defined(CS_TDS_50) if (CS_SEVERITY(msg->msgnumber) >= CS_SV_COMM_FAIL || ctx == NULL || con == NULL) - */ +#else + /* Then we use freetds which uses enum instead of defines */ if ((CS_SEVERITY(msg->msgnumber) >= CS_SV_COMM_FAIL && CS_SEVERITY(msg->msgnumber) <= CS_SV_FATAL) || ctx == NULL || con == NULL) +#endif { fprintf (stderr, "%s: Aborting on severity %d\n", server, (int) CS_SEVERITY(msg->msgnumber) ); sqsh_exit(254); @@ -1939,14 +2046,16 @@ ShowNetAuthCredExp (conn, cmdname) #endif } + /* - * connect_signal(): + * connect_run_sigint(): * * This function is called whenever a SIGINT signal is received while processing cmd_connect. - * Its only real job is to abort the connection attempt and leave sqsh. + * Its only real job is to return to the point where the SETJMP function was executed. */ -static void connect_signal (int sig, void *user_data ) +static void connect_run_sigint (int sig, void *user_data ) { - sqsh_exit (254); + sg_interrupted = True; + LONGJMP (sg_jmp_buf, 1); } diff --git a/src/cmd_input.c b/src/cmd_input.c index 7685bbf..2a9172c 100644 --- a/src/cmd_input.c +++ b/src/cmd_input.c @@ -52,7 +52,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_input.c,v 1.7 2012/03/29 16:25:46 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: cmd_input.c,v 1.8 2013/04/25 14:09:47 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -74,8 +74,8 @@ static int DynKeywordLoad _ANSI_ARGS(( void )); /* sqsh-2.1.8 - Feature d /* - * sg_jmp_buf: The following buffer is used to contain the location - * to which this module will return upon receipt of a + * sg_jmp_buf: The following buffer is used to contain the location + * to which this module will return upon receipt of a * SIGINT. It is only used while waiting on input from the * user. */ @@ -122,7 +122,6 @@ int cmd_input() int exit_status ; /* Exit status of sub-command */ JMP_BUF old_jmp_buf ; /* Store the previous jmp_buf */ int is_cmd ; /* True if the current line is cmd */ - int no_hist ; /* True if hist should not be updt. */ job_id_t job_id ; /* Id of job launched or completed */ char *defer_file ; /* Name of file holding user output */ struct stat stat_buf ; /* Check for defer file's existence */ @@ -134,6 +133,11 @@ int cmd_input() int cur_lineno; int interactive; + /* + * sqsh-2.2.0 - Extension on semicolon_hack + */ + char *semicolon_hack2 ; /* Value of $semicolon_hack2 */ + char *str_remainder = NULL; /* Remainder of input string after ; */ /* * Variables that need to be restored before turning to the @@ -245,7 +249,7 @@ int cmd_input() */ env_get( g_env, "keyword_dynamic", &keyword_dynamic ); env_get( g_internal_env, "keyword_refresh", &keyword_refresh ); - if (interactive && + if (interactive && keyword_refresh != NULL && *keyword_refresh != '0' && keyword_dynamic != NULL && *keyword_dynamic != '0') { @@ -254,37 +258,50 @@ int cmd_input() } #endif - no_hist = False; /* Save history for this buffer */ - /* - * Clear out the buffer that will be used to place input read - * from the user. + * sqsh-2.2.0 - Semicolon_hack2. If str_remainder is not NULL + * then we have a leftover from the previous loop were a ; + * has been processed. So this part of the input should be + * processed next. The else branch executes the pre-sqsh-2.2.0 + * code path. */ - varbuf_clear( read_buf ); + if (str_remainder != NULL) + { + str = str_remainder; + str_remainder = NULL; + } + else + { + /* + * Clear out the buffer that will be used to place input read + * from the user. + */ + varbuf_clear( read_buf ); - /* - * If an input_file was supplied, or no input string was supplied - * then call input_read. By default, if input_read gets a NULL - * input_file, stdin is used. - */ - ret = input_read( read_buf, interactive ); + /* + * If an input_file was supplied, or no input string was supplied + * then call input_read. By default, if input_read gets a NULL + * input_file, stdin is used. + */ + ret = input_read( read_buf, interactive ); - if (ret <= 0) - { - if (ret == 0) + if (ret <= 0) { - goto loop_leave; + if (ret == 0) + { + goto loop_leave; + } + fprintf( stderr, "input: %s\n", sqsh_get_errstr() ); + goto loop_abort; } - fprintf( stderr, "input: %s\n", sqsh_get_errstr() ); - goto loop_abort; + + /* + * Pull contents of read_buf out. + */ + str = varbuf_getstr( read_buf ); } /* - * Pull contents of read_buf out. - */ - str = varbuf_getstr( read_buf ); - - /* * The first thing we need to determine is if the current * line contains a sqsh command. This information will be * used in several places. @@ -301,7 +318,7 @@ int cmd_input() * then we pretend it is a buffer recall. So, we turn * it into a logical call to \buf-append. */ - if (is_cmd == False && interactive && *str == '!' && + if (is_cmd == False && interactive && *str == '!' && !isspace((int)*(str+1))) { @@ -341,50 +358,93 @@ int cmd_input() * input_strchr(), returns the first ';' in str that will not * be contained in double quotes when str is appended to * g_sqlbuf. + * sqsh-2.2.0 - If semicolon_hack2 is set, it doesn't matter + * if the input line is a command or not. We still want to + * process possible semicolons. So that makes the if statement + * a bit more complex. */ - env_get( g_env, "semicolon_hack", &semicolon_hack ); - if (semicolon_hack != NULL && *semicolon_hack == '1' && !is_cmd && - strchr( str, ';') != NULL && - (ch = input_strchr( g_sqlbuf, str, ';' )) != NULL) + env_get( g_env, "semicolon_hack", &semicolon_hack ); + env_get( g_env, "semicolon_hack2", &semicolon_hack2 ); + if ( (strchr( str, ';') != NULL && (ch = input_strchr( g_sqlbuf, str, ';' )) != NULL) && + ((semicolon_hack != NULL && *semicolon_hack == '1' && !is_cmd) || + (semicolon_hack2 != NULL && *semicolon_hack2 == '1')) + ) { /* - * Copy everything up to the ';' into the current work buffer. - */ - if (ch - str != 0) - { - varbuf_strncat( g_sqlbuf, str, ch - str ); - varbuf_charcat( g_sqlbuf, '\n' ); - - /* - * We now have an extra line. - */ - env_set( g_env, "lineno", "+1" ); - } - - /* * Look up the name of the command that the user wishes * to use when a semicolon is encountered. */ env_get( g_env, "semicolon_cmd", &semicolon_cmd ); - if (semicolon_cmd == NULL || *semicolon_cmd == '\0') - { varbuf_strcpy( sg_buf, "\\go " ); - } else - { varbuf_strcpy( sg_buf, semicolon_cmd ); - varbuf_charcat( sg_buf, ' ' ); - } /* - * Now, stick the semicolon command in the front of everything - * following the semicolon. and turn that into the command - * line. + * sqsh-2.2.0 - The hack is going to be even worse and worse. + * If semicolon_hack2 is set, then we treat a ; as a + * command or batch separator, execute the portion before + * the ; as a SQL buffer, or as a sqsh command. The remainder + * of the string after the ; is saved for later use. */ - varbuf_strcat( sg_buf, ch + 1 ); + if (semicolon_hack2 != NULL && *semicolon_hack2 == '1') + { + /* + * replace the ; with end of line + */ + *ch = '\0'; + /* + * save the remainder of the string in str_remainder + * or set it to NULL if there is really nothing left + */ + str_remainder = ch + 1; + if (*str_remainder == '\n' || *str_remainder == '\0') + str_remainder = NULL; + /* + * Check if we have to deal with a sqsh command or + * a SQL statement, at least the last part of it. + */ + if (!is_cmd && jobset_is_cmd( g_jobset, str ) == False) + { + if (ch - str != 0) + { + varbuf_strncat( g_sqlbuf, str, ch - str ); + varbuf_charcat( g_sqlbuf, '\n' ); + env_set( g_env, "lineno", "+1" ); + } + str = varbuf_getstr( sg_buf ); + } + /* else the current str is a sqsh command */ + } + else + { + /* + * Original pre-sqsh-2.2.0 code path with only + * semicolon_hack set to true. + */ + /* + * Copy everything up to the ';' into the current work buffer. + */ + if (ch - str != 0) + { + varbuf_strncat( g_sqlbuf, str, ch - str ); + varbuf_charcat( g_sqlbuf, '\n' ); + + /* + * We now have an extra line. + */ + env_set( g_env, "lineno", "+1" ); + } - str = varbuf_getstr( sg_buf ); + /* + * Now, stick the semicolon command in the front of everything + * following the semicolon. and turn that into the command + * line. + */ + varbuf_charcat( sg_buf, ' ' ); + varbuf_strcat( sg_buf, ch + 1 ); + str = varbuf_getstr( sg_buf ); + } is_cmd = True; } @@ -474,7 +534,7 @@ int cmd_input() * if $interactive is set to 0, then this entry will * automatically be thrown away. */ - if (!no_hist && interactive) + if (interactive) { history_append( g_history, varbuf_getstr(g_sqlbuf) ); @@ -488,8 +548,8 @@ int cmd_input() case CMD_CLEARBUF: /* - * sqsh-2.1.7 - The same as CMD_RESETBUF but without - * saving the buffer to the history. + * sqsh-2.1.7 - The same as CMD_RESETBUF but without + * saving the buffer to the history. */ varbuf_clear( g_sqlbuf ); env_set( g_env, "lineno", "=1" ) ; /* Set to 1 */ @@ -530,7 +590,6 @@ int cmd_input() case CMD_ABORT : goto loop_abort; break; - default : sprintf( number, "=%d", cur_lineno ); @@ -546,7 +605,7 @@ int cmd_input() * jobset_run() returned a non-negative value, so it launched * a background process. The only thing we need to do it * let the user know it was launched. - * sqsh-2.1.7 - Also save and clear the command buffer. + * sqsh-2.1.7 - Also save and clear the command buffer. */ default : if (interactive) @@ -554,14 +613,11 @@ int cmd_input() job_pid = jobset_get_pid( g_jobset, job_id ); fprintf( stdout, "Job #%d running [%d]\n", (int)job_id, (int)job_pid ); - if (!no_hist) - { - history_append( g_history, varbuf_getstr(g_sqlbuf) ); + history_append( g_history, varbuf_getstr(g_sqlbuf) ); - /*-- Set histnum to be current history number --*/ - sprintf( number, "%d", history_get_nbr(g_history) ); - env_set( g_env, "histnum", number ); - } + /*-- Set histnum to be current history number --*/ + sprintf( number, "%d", history_get_nbr(g_history) ); + env_set( g_env, "histnum", number ); varbuf_clear( g_sqlbuf ); env_set( g_env, "lineno", "=1" ) ; /* Set to 1 */ } @@ -576,7 +632,7 @@ int cmd_input() * than each time the user hits return. */ job_id = 0; - while(interactive && + while(interactive && (job_id = jobset_wait(g_jobset, -1, &exit_status, JOB_NONBLOCK)) > 0) { /* @@ -674,7 +730,7 @@ loop_done : if (read_buf != NULL) varbuf_destroy( read_buf ); - + /* * Restore the line number to its previous value. */ @@ -692,7 +748,7 @@ loop_done : varbuf_destroy( g_sqlbuf ); g_sqlbuf = (varbuf_t*)orig_sqlbuf; } - + /* * Restore the original signal context, and, just in case * cmd_loop() has been recursively called, restore the original @@ -725,7 +781,7 @@ static int input_read( output_buf, interactive ) char *exp_prompt = NULL; /* - * If we are in interactive mode then we need to display a + * If we are in interactive mode then we need to display a * prompt to the user. */ if (interactive) @@ -733,7 +789,7 @@ static int input_read( output_buf, interactive ) /* * If we haven't already allocated a buffer in which to * expand the prompt then we should do so. - * sqsh-2.1.6 - expand buffer from 32 to 64 bytes. + * sqsh-2.1.6 - expand buffer from 32 to 64 bytes. */ if (sg_prompt_buf == NULL) { @@ -761,13 +817,13 @@ static int input_read( output_buf, interactive ) if (!is_continued) { env_get( g_env, "prompt", &prompt ); - if( prompt == NULL || *prompt == '\0' ) + if( prompt == NULL || *prompt == '\0' ) prompt = "${lineno}> "; } else { env_get( g_env, "prompt2", &prompt ); - if( prompt == NULL || *prompt == '\0' ) + if( prompt == NULL || *prompt == '\0' ) prompt = "--> "; } @@ -780,7 +836,7 @@ static int input_read( output_buf, interactive ) fprintf( stderr, "prompt: %s\n", sqsh_get_errstr() ); varbuf_strcpy( sg_prompt_buf, "?> " ); } - + exp_prompt = varbuf_getstr(sg_prompt_buf); } else @@ -898,13 +954,13 @@ static char* input_strchr( varbuf, str, c ) case QUOTE_NONE: switch (*cptr) { - case '\'': + case '\'': quote_type = QUOTE_SINGLE; break; - case '\"': + case '\"': quote_type = QUOTE_DOUBLE; break; - case '/' : + case '/' : if (*(cptr + 1) == '*') quote_type = QUOTE_COMMENT; break; @@ -922,28 +978,28 @@ static char* input_strchr( varbuf, str, c ) break; } break; - + case QUOTE_COMMENT: if (*cptr == '*' && *(cptr + 1) == '/') { quote_type = QUOTE_NONE; } break; - + case QUOTE_SINGLE: if (*cptr == '\'') { quote_type = QUOTE_NONE; } break; - + case QUOTE_DOUBLE: if (*cptr == '\"') { quote_type = QUOTE_NONE; } break; - + default: break; } @@ -960,13 +1016,13 @@ static char* input_strchr( varbuf, str, c ) case QUOTE_NONE: switch (*cptr) { - case '\'': + case '\'': quote_type = QUOTE_SINGLE; break; - case '\"': + case '\"': quote_type = QUOTE_DOUBLE; break; - case '/' : + case '/' : if (*(cptr + 1) == '*') quote_type = QUOTE_COMMENT; break; @@ -984,28 +1040,28 @@ static char* input_strchr( varbuf, str, c ) break; } break; - + case QUOTE_COMMENT: if (*cptr == '*' && *(cptr + 1) == '/') { quote_type = QUOTE_NONE; } break; - + case QUOTE_SINGLE: if (*cptr == '\'') { quote_type = QUOTE_NONE; } break; - + case QUOTE_DOUBLE: if (*cptr == '\"') { quote_type = QUOTE_NONE; } break; - + default: break; } @@ -1076,13 +1132,13 @@ static int DynKeywordLoad () keyword_query, /* Buffer */ CS_NULLTERM, /* Buffer Length */ CS_UNUSED /* Options */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { ct_cmd_drop( cmd ); DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Call to ct_command failed.\n")); return (CS_FAIL); } - if (ct_send( cmd ) != CS_SUCCEED) + if (ct_send( cmd ) != CS_SUCCEED) { ct_cmd_drop( cmd ); DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Call to ct_send failed.\n")); diff --git a/src/cmd_reconnect.c b/src/cmd_reconnect.c index 3e0ce2c..7eb4818 100644 --- a/src/cmd_reconnect.c +++ b/src/cmd_reconnect.c @@ -30,7 +30,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_reconnect.c,v 1.2 2013/04/04 10:52:35 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_reconnect.c,v 1.3 2013/04/25 14:09:47 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -39,19 +39,27 @@ USE(RCS_Id) * * Re-establishes a connection the database, closing the prior * connection. This allows, essentially, an 'su' for databases. + * + * sqsh-2.2.0 - Also save the current context and let ct_connect setup + * a new context. In case of success we can drop the original context, + * otherwise restore the original context. */ int cmd_reconnect( argc, argv ) int argc ; char *argv[] ; { CS_CONNECTION *old_connection; + CS_CONTEXT *old_context; old_connection = g_connection; + old_context = g_context; g_connection = NULL; + g_context = NULL; if( cmd_connect( argc, argv ) == CMD_FAIL ) { g_connection = old_connection ; + g_context = old_context ; return CMD_FAIL ; } @@ -59,5 +67,9 @@ int cmd_reconnect( argc, argv ) ct_close( old_connection, CS_FORCE_CLOSE ); ct_con_drop( old_connection ); + if (ct_exit( old_context, CS_UNUSED ) != CS_SUCCEED) + ct_exit( old_context, CS_FORCE_EXIT ); + cs_ctx_drop( old_context ); + return CMD_LEAVEBUF ; } diff --git a/src/sqsh_debug.h b/src/sqsh_debug.h index a9861ec..be06006 100644 --- a/src/sqsh_debug.h +++ b/src/sqsh_debug.h @@ -40,6 +40,7 @@ #define DEBUG_ERROR (1<<12) /* Debug error handlers */ #define DEBUG_SIG (1<<13) /* Debug signal handlers */ #define DEBUG_HISTORY (1<<14) /* Debug history processing */ +#define DEBUG_TDS (1<<15) /* Debug TDS protocol CS communications */ #define DEBUG_ALL ~(0) /* Turn on all debugging */ #if defined(DEBUG) diff --git a/src/sqsh_env.c b/src/sqsh_env.c index 5e0b1d0..33cc8fa 100644 --- a/src/sqsh_env.c +++ b/src/sqsh_env.c @@ -29,7 +29,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_env.c,v 1.1 2004/04/07 12:35:05 chunkm0nkey Exp $"; +static char RCS_Id[] = "$Id: sqsh_env.c,v 1.2 2013/04/25 14:09:47 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -57,14 +57,14 @@ env_t* env_create( hsize ) if (hsize < 1) { sqsh_set_error( SQSH_E_BADPARAM, NULL ); - return False; + return NULL; } /*-- Attempt to allocate an environment --*/ if ((e = (env_t*)malloc(sizeof(env_t))) == NULL) { sqsh_set_error( SQSH_E_NOMEM, NULL ); - return False; + return NULL; } /*-- Create the hash table --*/ @@ -72,7 +72,7 @@ env_t* env_create( hsize ) { free( e ); sqsh_set_error( SQSH_E_NOMEM, NULL ); - return False; + return NULL; } for (i = 0; i < hsize; i++) @@ -196,12 +196,16 @@ int env_remove( e, var_name, flags ) */ if (e->env_save != NULL && (flags & ENV_F_TRAN) != 0) { + DBG(sqsh_debug( DEBUG_ENV, "env_remove: Variable '%s' with value '%s' deleted in TRAN\n", + v->var_name , v->var_value);) v->var_sptype = ENV_SP_REMOVE; v->var_nxt = e->env_save; e->env_save = v; } else { + DBG(sqsh_debug( DEBUG_ENV, "env_remove: Variable '%s' with value '%s' deleted\n", + v->var_name , v->var_value);) var_destroy( v ); } @@ -297,10 +301,11 @@ int env_put( e, var_name, value, flags ) return False; } - new_v->var_sptype = ENV_SP_CHANGE; new_v->var_nxt = e->env_save; e->env_save = new_v; + DBG(sqsh_debug( DEBUG_ENV, "env_put: Variable '%s' changed from '%s' to '%s' in TRAN\n", + v->var_name , v->var_value, value );) } /* @@ -316,6 +321,22 @@ int env_put( e, var_name, value, flags ) } else { + if (e->env_save != NULL && (flags & ENV_F_TRAN) != 0) + { + new_v = var_create( var_name, value ); + + if (new_v == NULL) + { + return False; + } + + new_v->var_sptype = ENV_SP_NEW; + new_v->var_nxt = e->env_save; + e->env_save = new_v; + DBG(sqsh_debug( DEBUG_ENV, "env_put: Variable '%s' with value '%s' added in TRAN\n", + var_name , value );) + } + /* * The variable doesn't exist, so create it and stick it * into the hash table. @@ -345,7 +366,7 @@ int env_put( e, var_name, value, flags ) * if a 'get' validation function exists for the variable, then it is called. * Upon success, 1 is returned with value containing the value of var_name, * otherwise 0 is returned if the variable doesn't exist, or a -1 - * is retuend if the validation function failed, or some other error condition + * is returned if the validation function failed, or some other error condition * ocurred. */ int env_nget( e, var_name, value, n ) @@ -357,6 +378,9 @@ int env_nget( e, var_name, value, n ) var_t *v; int hval; char *cptr; +#if defined(DEBUG) + char *dbg_var_name; +#endif /*-- Always check your arguments --*/ if (e == NULL || var_name == NULL) @@ -390,15 +414,19 @@ int env_nget( e, var_name, value, n ) } #if defined(DEBUG) + dbg_var_name = sqsh_strdup (var_name); + if (n >= 0) + dbg_var_name[n] = '\0'; if (v == NULL) { - sqsh_debug( DEBUG_ENV, "env_nget: Miss on %s, checking environment.\n", - var_name ); + sqsh_debug( DEBUG_ENV, "env_nget: Miss on variable '%s', checking OS environment\n", + dbg_var_name ); } else { - sqsh_debug( DEBUG_ENV, "env_nget: Hit on %s.\n", var_name ); + sqsh_debug( DEBUG_ENV, "env_nget: Hit on variable '%s'\n", dbg_var_name ); } + free (dbg_var_name); #endif /* DEBUG */ /* @@ -421,7 +449,7 @@ int env_nget( e, var_name, value, n ) /* * If we are only interested in part of a string, then - * we need to need to create a temporary buffer in which + * we need to create a temporary buffer in which * to place the partial string to pass it to getenv. */ if (n >= 0) @@ -505,37 +533,12 @@ int env_nget( e, var_name, value, n ) return 1; } -int env_print( e ) - env_t *e; -{ - int i; - var_t *v; - - if (e == NULL) - { - sqsh_set_error( SQSH_E_BADPARAM, NULL ); - return False; - } - - for (i = 0; i < e->env_hsize; i++) - { - for (v = e->env_htable[i]; v != NULL; v = v->var_nxt) - { - printf("%s = %s\n", - v->var_name != NULL ? v->var_name : "NULL", - v->var_value != NULL ? v->var_value : "NULL" ); - } - } - - sqsh_set_error( SQSH_E_NONE, NULL ); - return True; -} /* * env_tran(): * * Create a transaction "save-point" in the environment. After - * calling env_tran(), subsequnt calls to env_put() or env_remove() + * calling env_tran(), subsequent calls to env_put() or env_remove() * with a flag of ENV_F_TRAN will cause the resulting change to * be logged. A call to env_rollback() will restore all logged * changes to be reversed, and a call to env_commit() ends the @@ -576,33 +579,34 @@ int env_rollback( e ) var_t *v; /* - * Now, blast through our save stack, reseting each variable + * Now, blast through our save stack, resetting each variable * to its original state. */ while (e->env_save != NULL && e->env_save->var_sptype != ENV_SP_START) { v = e->env_save; - e->env_save = e->env_save->var_nxt; + e->env_save = v->var_nxt; switch (v->var_sptype) { case ENV_SP_NEW: DBG(sqsh_debug( DEBUG_ENV, - "env_rollback: Removing '%s'\n", v->var_name );) + "env_rollback: Removing variable '%s'\n", v->var_name );) env_remove( e, v->var_name, 0 ); break; case ENV_SP_CHANGE: DBG(sqsh_debug( DEBUG_ENV, - "env_rollback: Restoring '%s' to '%s'\n", + "env_rollback: Restoring variable '%s' to '%s'\n", v->var_name, v->var_value );) env_put( e, v->var_name, v->var_value, 0 ); break; case ENV_SP_REMOVE: DBG(sqsh_debug( DEBUG_ENV, - "env_rollback: Adding '%s'\n", v->var_name );) + "env_rollback: Adding variable '%s' with value '%s'\n", + v->var_name, v->var_value );) env_set_valid( e, v->var_name, v->var_value, v->var_setf, v->var_getf ); @@ -619,10 +623,10 @@ int env_rollback( e ) if (e->env_save != NULL) { v = e->env_save; - e->env_save = e->env_save->var_nxt; + e->env_save = v->var_nxt; var_destroy( v ); } - DBG(sqsh_debug( DEBUG_ENV, "env_save: Save-point restored\n" );) + DBG(sqsh_debug( DEBUG_ENV, "env_rollback: Save-point rolled-back\n" );) return True; } @@ -646,11 +650,7 @@ int env_commit( e ) e->env_save = v->var_nxt; var_destroy( v ); } - else - { - e->env_save = NULL; - } - DBG(sqsh_debug( DEBUG_ENV, "env_commit: Save-point restored\n" );) + DBG(sqsh_debug( DEBUG_ENV, "env_commit: Save-point committed\n" );) return True; } @@ -803,6 +803,7 @@ static var_t* var_create( var_name, value ) v->var_sptype = ENV_SP_NONE; v->var_setf = NULL; v->var_getf = NULL; + v->var_nxt = NULL; return v; } diff --git a/src/sqsh_env.h b/src/sqsh_env.h index 8c5e529..d7d934b 100644 --- a/src/sqsh_env.h +++ b/src/sqsh_env.h @@ -59,13 +59,12 @@ int env_set_valid _ANSI_ARGS(( env_t*, char*, char*, env_f*, env_f* )); int env_set _ANSI_ARGS(( env_t*, char*, char* )); int env_put _ANSI_ARGS(( env_t*, char*, char*, int )); int env_remove _ANSI_ARGS(( env_t*, char*, int )); -int env_del _ANSI_ARGS(( env_t*, char* )); -int env_get _ANSI_ARGS(( env_t*, char*, char** )); int env_nget _ANSI_ARGS(( env_t*, char*, char**, int )); int env_tran _ANSI_ARGS(( env_t* )); int env_commit _ANSI_ARGS(( env_t* )); int env_rollback _ANSI_ARGS(( env_t* )); int env_destroy _ANSI_ARGS(( env_t* )); +/* int env_get _ANSI_ARGS(( env_t*, char*, char** )); */ #define env_get(e,k,v) env_nget(e,k,v,-1) diff --git a/src/sqsh_expand.c b/src/sqsh_expand.c index 555ddbb..3da6e5d 100644 --- a/src/sqsh_expand.c +++ b/src/sqsh_expand.c @@ -36,7 +36,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_expand.c,v 1.6 2013/04/04 10:52:36 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: sqsh_expand.c,v 1.7 2013/04/25 14:09:47 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -722,8 +722,34 @@ static int expand_variable( cpp, str_end, buf, flags ) *cpp = str; return True; } + + /* + * Check for special cases. + * sqsh-2.2.0 - First, $? is the result of last action. + */ + if (*var_name_start == '?' && + (var_name_end - var_name_start) == 1) + { + env_get( g_internal_env, "?", &var_value ); + varbuf_strcat( buf, var_value ); + *cpp = str; + return(True); + } + + /* + * Next, $$ is the current processid. + */ + if (*var_name_start == '$' && + (var_name_end - var_name_start) == 1) + { + sprintf(nbr, "%d", (int) getpid() ); + varbuf_strcat( buf, nbr ); + *cpp = str; + return(True); + } + /* - * Check for special case. First, $# is the number of arguments. + * Next, $# is the number of arguments. */ if (*var_name_start == '#' && (var_name_end - var_name_start) == 1) @@ -745,19 +771,6 @@ static int expand_variable( cpp, str_end, buf, flags ) return(True); } - - /* - * Next, $$ is the current processid. - */ - if (*var_name_start == '$' && - (var_name_end - var_name_start) == 1) - { - sprintf(nbr, "%d", (int) getpid() ); - varbuf_strcat( buf, nbr ); - *cpp = str; - return(True); - } - /* * Next, $* is the complete list of arguments. */ diff --git a/src/sqsh_history.c b/src/sqsh_history.c index 500abca..2978d1a 100644 --- a/src/sqsh_history.c +++ b/src/sqsh_history.c @@ -33,7 +33,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_history.c,v 1.8 2013/04/18 11:54:43 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_history.c,v 1.9 2013/04/25 14:09:47 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -414,6 +414,7 @@ int history_del( h, idx ) hb != NULL; hb->hb_nbr = i--, hb = hb->hb_nxt); break; } + h->h_change = HISTSAVE_FORCE; hist_auto_save ( h ); return True ; @@ -528,9 +529,13 @@ int history_save( h, save_file ) /* * sqsh-2.2.0 - Merge the history file with the buffers in memory. + * If h_change is set to HISTSAVE_FORCE then we do not want to + * merge, because we may have just removed a bunch of buffers + * for example. */ env_get (g_env, "histmerge", &histmerge); - if ( histmerge != NULL && *histmerge == '1') + if ( histmerge != NULL && *histmerge == '1' && + h->h_change != HISTSAVE_FORCE) { x = history_create (history_get_size(h)); if (history_load (x, save_file) == True) diff --git a/src/sqsh_init.c b/src/sqsh_init.c index 55c2d62..0729928 100644 --- a/src/sqsh_init.c +++ b/src/sqsh_init.c @@ -44,7 +44,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_init.c,v 1.4 2013/04/04 10:52:36 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_init.c,v 1.5 2013/04/25 14:09:47 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -223,6 +223,12 @@ int sqsh_init() varbuf_destroy( expand_buf ) ; /* + * sqsh-2.2.0 - Initialize variable keyword_refresh in the + * g_internal_env to prevent misses in subsequent variable lookups. + */ + env_set( g_internal_env, "keyword_refresh", "0" ); + + /* * Allocate our global set of sub-processes. */ if( (g_jobset = jobset_create( 47 )) == NULL ) { @@ -345,6 +351,11 @@ void sqsh_exit( exit_status ) g_buf = NULL; } + if ( g_internal_env != NULL ) { + env_destroy( g_internal_env ) ; + g_internal_env = NULL; + } + /* * sqsh-2.1.7 - Reset term_title. */ diff --git a/src/sqsh_main.c b/src/sqsh_main.c index 9b6a99b..29601b7 100644 --- a/src/sqsh_main.c +++ b/src/sqsh_main.c @@ -42,7 +42,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_main.c,v 1.22 2013/04/18 11:54:43 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: sqsh_main.c,v 1.23 2013/04/25 14:09:47 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -162,6 +162,15 @@ main( argc, argv ) varbuf_t *exp_buf; /* + * sqsh-2.2.0 - Variables used by password handling option + * moved here. + */ + char buf[MAXPWD]; + char *p; + int fdin, fdout; + + + /* * If termios.h defines TIOCGWINSZ, then we need to declare a * structure in which to retrieve the current window size. */ @@ -368,7 +377,6 @@ main( argc, argv ) read_file = True; show_banner = False; ret = env_set( g_env, "script", sqsh_optarg ); - ret = env_set( g_internal_env, "0", sqsh_optarg ); break; case 'I' : ret = env_set( g_env, "interfaces", sqsh_optarg ); @@ -516,10 +524,6 @@ main( argc, argv ) * to solve a problem with pipes already in use. (Patch-id 2607434) * The actual pipe file descriptors will now be passed on with the \250 option. */ - char buf[MAXPWD]; - char *p; - int fdin, fdout; - memset(buf, 0, MAXPWD); if (sqsh_optarg != NULL) strcpy (buf, sqsh_optarg); @@ -585,7 +589,7 @@ main( argc, argv ) { if (sqsh_optind > 1) { - argv[sqsh_optind-1] = argv[0]; + env_get (g_env, "script", &(argv[sqsh_optind-1])) ; } g_func_args[g_func_nargs].argc = argc - sqsh_optind + 1; g_func_args[g_func_nargs].argv = &(argv[sqsh_optind-1]); @@ -1015,7 +1019,6 @@ static void hide_password (argc, argv) char *argv[]; { int i, j; - char **argn; char buf[32]; int filedes[2]; char nullpwd[2]; @@ -1024,10 +1027,6 @@ static void hide_password (argc, argv) int status; - /* - * sqsh-2.2.0 - Allocate memory for a complete new argument list. - */ - argn = malloc (sizeof(char*)*argc); nullpwd[0] = '\n'; nullpwd[1] = '\0'; @@ -1043,7 +1042,7 @@ static void hide_password (argc, argv) * New password parameter encounterd. */ pwd = NULL; - if (*(argv[i]+2)) + if (*(argv[i]+2) != '\0') { /* * Password passed on as: "sqsh -SSYBASE -Usa -Pxxxxxx" , or as -P- @@ -1067,7 +1066,7 @@ static void hide_password (argc, argv) } } else - argn[j++] = argv[i]; + argv[j++] = argv[i]; } /* @@ -1076,7 +1075,6 @@ static void hide_password (argc, argv) */ if (pwd == NULL) { - free (argn); return; } @@ -1089,21 +1087,21 @@ static void hide_password (argc, argv) return; } sprintf (buf, "-%c%d/%d", '\250', filedes[0], filedes[1]); - argn[j++] = buf; - argn[j] = NULL; + argv[j++] = buf; + argv[j] = NULL; - if ((pid = fork())) + if ((pid = fork()) != 0) { /* * sqsh-2.2.0 - This code is executed by the parent process. * Wait for the child process to finish execution before we continue. */ - waitpid (pid, &status, 0); + (void) waitpid (pid, &status, 0); /* - * Re-execute ourselves in the parent process, with the new argn[] list. + * Re-execute ourselves in the parent process, with the modified argv[] list. */ - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) - execvp (argn[0], argn); + if (WIFEXITED(status) != 0 && WEXITSTATUS(status) == 0) + (void) execvp (argv[0], argv); /* Not reached */ else { @@ -1117,13 +1115,13 @@ static void hide_password (argc, argv) * The child process writes the password to the pipe, closes the pipe * and exits. */ - if (write (filedes[1], pwd, strlen(pwd)) != strlen(pwd)) + if ((int) write (filedes[1], pwd, strlen(pwd)) != (int) strlen(pwd)) { fprintf (stderr, "sqsh: Error: Failed to write password to pipe (filedes=%d)\n", filedes[1]); sqsh_exit (255); } - close (filedes[0]); - close (filedes[1]); + (void) close (filedes[0]); + (void) close (filedes[1]); sqsh_exit (0); } } @@ -195,9 +195,15 @@ static var_entry_t sg_var_entry[] = { /* sqsh-2.1.9 - New variables */ { "datefmt", NULL, var_set_datefmt, var_get_datefmt }, { "timefmt", NULL, var_set_timefmt, var_get_timefmt }, - /* sqsh-2.2.0 - New variables */ + /* sqsh-2.2.0 - New or missing variables in global env added */ + { "autouse", NULL, var_set_nullstr, NULL }, + { "debug_tds_logdata",NULL, var_set_nullstr, NULL }, + { "debug_tds_capture",NULL, var_set_nullstr, NULL }, + { "histmerge", "0", var_set_bool, NULL }, { "readline_histignore", NULL, var_set_nullstr, NULL }, - { "histmerge", "0", var_set_bool, NULL }, + { "script", NULL, var_set_nullstr, NULL }, + { "semicolon_hack2", "0", var_set_bool, NULL }, + { "tds_version", NULL, var_set_nullstr, NULL }, } ; #endif /* SQSH_INIT */ diff --git a/src/var_debug.c b/src/var_debug.c index eabda05..f0a6f10 100644 --- a/src/var_debug.c +++ b/src/var_debug.c @@ -32,7 +32,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_debug.c,v 1.3 2013/04/18 11:54:43 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: var_debug.c,v 1.4 2013/04/25 14:09:48 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -65,6 +65,7 @@ struct debug_st { { "SIG", DEBUG_SIG }, { "SIGCHLD", DEBUG_SIGCLD }, { "SIGCLD", DEBUG_SIGCLD }, + { "TDS", DEBUG_TDS }, } ; #endif |