diff options
author | Steve Langasek <vorlon@debian.org> | 2018-09-25 18:09:57 +0000 |
---|---|---|
committer | Steve Langasek <vorlon@debian.org> | 2018-09-25 18:09:57 +0000 |
commit | 69655f449e92e084124567be02e586bd907cb024 (patch) | |
tree | f08bf6b283c3fd2e068615e6ce6612d9b548b573 /src | |
parent | 96fd3f2d6c95d48a0676a23c1aaae6b45d6e4943 (diff) | |
parent | 2b2cc5a50fc4a4a71c9a722c6e70a46916504e3e (diff) |
New upstream release
Diffstat (limited to 'src')
70 files changed, 8865 insertions, 3470 deletions
diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index a845ecf..0000000 --- a/src/Makefile +++ /dev/null @@ -1,533 +0,0 @@ -# -# Makefile.in,v 1.4 1996/02/15 02:18:28 gray Exp -# - -# The following list of sqshrc files will be executed by sqsh upon -# startup. This allows for system-wide defaults to be set in a -# common directory. If you don't want a global sqshrc just comment -# out SQSHRC_GLOBAL, below. - -SQSHRC_GLOBAL = /usr/local/etc/sqshrc -SQSHRC_PATH = "$(SQSHRC_GLOBAL):$${HOME}/.sqshrc" - -# The following variables are configurable by the user. Typically -# these include things that GNU autoconf has a little trouble -# figuring out for itself. - -SYBASE_OCOS = /opt/sybase/OCS-15_0 -SYBASE_INCDIR = -I$(SYBASE_OCOS)/include -SYBASE_LIBDIR = -L$(SYBASE_OCOS)/lib - -# -# The following set of CT-LIB libraries were determined automatically -# by 'configure'. For most systems configure looks up the required -# libraries by looking at the name of the OS (although this doesn't -# mean it got them right), however if the line below ends with the -# word "Guess", then 'configure' didn't have an entry for your operating -# system and it took a best guess to figure out which libraries you -# need. In either case, there may be problems, so look this line over -# and if it doesn't work, compare it to the libraries located in -# $SYBASE/samples/ctlibrary. -# -# The listings below show suggested libraries for Operating Systems -# that frequently fail to be recognized by 'configure': -# -# SCO: -lblk -lct -lcs -lcomn -ltcl -ltli -lnsl_s -lintl -m -lsocket -# Dynix: -lblk -lct -lcs -lcomn -ltcl -ltli -lnsl -lintl -lm -lseq -# -SYBASE_LIBS = -lsybblk -lsybcs -lsybct -lsybtcl -lsybcomn -lsybintl -ldl -lm - -# -# If you have the GNU readline library available, uncomment the -# following definitions and make sure the lib directory and -# include directories are correct. -# -DEF_READLINE = -DUSE_READLINE -DOLD_READLINE -READLINE_LIBDIR = # -L/lib -READLINE_INCDIR = # -I/usr/include - -# -# On most systems, -lreadline and -lcurses is enough to link with -# the readline library. However on a few systems you may need to -# link with termcap rather than curses, and on other systems (such -# as certain Solaris installations), you may need to link in -lucb -# to get around some BSD specifics dealing with the termcap library. -# -READLINE_LIBS = -lreadline -lcurses - -# -# Motif Support - The `configure' motif support logic for sqsh -# isn't exactly perfected yet. If --with-motif was run, the -# following what `configure' guessed at for the location -# for your Motif includes and libs. Note that if MOTIF_INCDIR -# and MOTIF_LIBDIR are commented out, then the X_INCDIR and -# X_LIBDIR will be used, below. -# -# Note that on some systems -lXpm may need to be added to -# MOTIF_LIBS. -# -DEF_MOTIF = # -DUSE_MOTIF -MOTIF_INCDIR = -MOTIF_LIBDIR = -MOTIF_LIBS = - -# -# X Windows Support -# -# The following variables configure whether or not X windows -# support is compiled into sqsh (this allows a result set to -# be displayed in a separate window). If '--with-x' was sup- -# plied to 'configure' then most of the variables should be -# filled in for you (read INSTALL). If '--with-x' was not -# supplied or '--without-x' was supplied then The following -# lines should be commented out. -# -DEF_X11 = # -DUSE_X11 -X_INCDIR = # -I/usr/X11R6/include -X_LIBDIR = # -L/usr/X11R6/lib -X_LIBS = $(MOTIF_LIBS) # -lXaw -lXt -lXext -lXmu -lX11 - -# -# Undefine the following line to turn off bcp support in sqsh. This -# feature allows a result set to be redirected (bcp'ed) to another -# server. Since this is a new feature, if you get compile errors on -# cmd_bcp.c, mail me a copy of the error message(s) (gray@voicenet.com) -# and uncomment this line. -# -#DEF_NOBCP = -DNO_BCP - -# -# As of sqsh-1.4, the $password value will never expand to a clear-text -# copy of the users password. If you wish to keep the old behavior -# (which did show the clear-text password), uncomment the following -# define. Note that this applies to the new $lock password as well. -# -#DEF_INSECURE = -DINSECURE - -# -# The following define turns on a work-around for a rather pernicious -# bug in CT-Lib having to do with the way that async i/o signals are -# delivered. If, while running sqsh, pipes tend to lose data or don't -# display anything at all, like: -# -# 1> sp_who -# 2> go | more -# 1> -# -# you probably have the bug. First, PLEASE e-mail me (gray@voicenet.com) -# and I'll give you a description of what is going on so you can call -# tech support: I am trying to get them to fix the problem, but they -# are moving at a snails pace. Then, when you have done that, un- -# comment the following line, which will attempt to install a work- -# around for the problem. -# -# Please, do not uncomment this line unless you have reproduced the -# behavior described above. -# -#DEF_BUGFIX = -DCTLIB_SIGPOLL_BUG - -# -# Uncommenting the following line turns on debugging support. Turning -# this feature on will increase the size of sqsh by about 12K, and -# will probably slow it down nominally. When enabled, various debugging -# messages may be turned on and off using the -l flag or the $debug -# environment variable. There is probably no reason to enable this -# unless you are debugging a problem or are interested in what is -# going on under the hood. -# -#DEF_DEBUG = -DDEBUG - -# -# End of user configuration section. -# - -prefix = /usr/local -src_dir = . -exec_prefix = ${prefix} -bin_dir = $(exec_prefix)/bin -inc_dir = $(prefix)/include -lib_dir = $(exec_prefix)/lib -man_src = $(src_dir)/doc -man_dir = $(prefix)/man - -INSTALL = $(src_dir)/autoconf/install-sh -INSTALL_PROG = $(INSTALL) -c -INSTALL_DIR = $(INSTALL) -d -INSTALL_DATA = $(INSTALL) -c -m 644 -INSTALL_MAN = $(src_dir)/autoconf/install-man - -CC = gcc -DEBUG = -DEFINES = -DSQSH_RC='${SQSHRC_PATH}' $(DEF_READLINE) \ - $(DEF_NOBCP) $(DEF_DEBUG) $(DEF_INSECURE) $(DEF_X11) \ - $(DEF_MOTIF) $(DEF_BUGFIX) -INCLUDE_DIRS = $(X_INCDIR) $(MOTIF_INCDIR) $(SYBASE_INCDIR) $(READLINE_INCDIR) -LIB_DIRS = $(X_LIBDIR) $(MOTIF_INCDIR) $(SYBASE_LIBDIR) $(READLINE_LIBDIR) -CFLAGS = -g -O2 $(DEBUG) $(DEFINES) $(INCLUDE_DIRS) -CPPFLAGS = -LDFLAGS = $(DEBUG) $(LIB_DIRS) -LIBS = $(SYBASE_LIBS) $(X_LIBS) $(READLINE_LIBS) - -# The follow define information about the components that make up -# the actual program. - -TARGET = sqsh - -CMDS = \ - cmd_alias.o cmd_bcp.o cmd_buf.o cmd_connect.o cmd_do.o \ - cmd_echo.o cmd_exit.o cmd_for.o cmd_func.o cmd_go.o \ - cmd_help.o cmd_history.o cmd_if.o cmd_input.o cmd_jobs.o \ - cmd_kill.o cmd_lock.o cmd_loop.o cmd_misc.o cmd_read.o \ - cmd_reconnect.o cmd_redraw.o cmd_reset.o cmd_return.o cmd_rpc.o \ - cmd_set.o cmd_shell.o cmd_show.o cmd_sleep.o cmd_wait.o \ - cmd_warranty.o cmd_while.o - -DISPLAYS = \ - dsp.o dsp_bcp.o dsp_csv.o dsp_conv.o dsp_desc.o dsp_horiz.o \ - dsp_html.o dsp_meta.o dsp_none.o dsp_out.o dsp_pretty.o \ - dsp_vert.o dsp_x.o - -VARS = \ - var_ctlib.o var_date.o var_debug.o var_dsp.o var_hist.o \ - var_misc.o var_passwd.o var_readline.o var_thresh.o - -CORE = \ - sqsh_alias.o sqsh_args.o sqsh_avl.o sqsh_buf.o sqsh_cmd.o \ - sqsh_compat.o sqsh_ctx.o sqsh_debug.o sqsh_env.o sqsh_error.o \ - sqsh_expand.o sqsh_fd.o sqsh_filter.o sqsh_fork.o sqsh_func.o \ - sqsh_getopt.o sqsh_global.o sqsh_history.o sqsh_init.o \ - sqsh_job.o sqsh_readline.o sqsh_sig.o sqsh_sigcld.o sqsh_stdin.o \ - sqsh_strchr.o sqsh_tok.o sqsh_varbuf.o - -OBJS = $(CMDS) $(VARS) $(DISPLAYS) $(CORE) - -MAN_PAGES = sqsh.1 -SRCS = $(OBJS:.o=.c) -HEADERS = - -$(TARGET) : $(OBJS) sqsh_main.o - $(CC) $(LDFLAGS) $(OBJS) sqsh_main.o $(LIBS) -o $@ - -sqsh_test : $(OBJS) sqsh_test.o - $(CC) $(LDFLAGS) $(OBJS) sqsh_test.o $(LIBS) -o $@ - -sig_test : sqsh_debug.o sqsh_error.o sqsh_sig.c - $(CC) $(LDFLAGS) $(DEF_DEBUG) -DSIG_TEST sqsh_debug.o sqsh_error.o \ - sqsh_sig.c -o sig_test - -clean : - rm -f *.o $(TARGET) sqsh_test sig_test - -realclean : clean - rm -f config.cache config.log config.status - -distclean : realclean - rm -f Makefile config.h core - -# -# The following absolutely disgusting list of dependancies was -# automatically generated via 'gcc -MM' -# -cmd_alias.o: cmd_alias.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_bcp.o: cmd_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_getopt.h sqsh_sig.h cmd.h -cmd_buf.o: cmd_buf.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_buf.h sqsh_stdin.h cmd.h -cmd_connect.o: cmd_connect.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h \ - sqsh_init.h sqsh_stdin.h cmd.h -cmd_do.o: cmd_do.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_buf.h \ - sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h \ - cmd_input.h -cmd_echo.o: cmd_echo.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_exit.o: cmd_exit.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h -cmd_for.o: cmd_for.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_buf.h \ - sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h \ - cmd_input.h -cmd_func.o: cmd_func.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_getopt.h sqsh_buf.h sqsh_stdin.h sqsh_readline.h cmd.h \ - cmd_misc.h cmd_input.h -cmd_go.o: cmd_go.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_getopt.h sqsh_buf.h \ - sqsh_filter.h sqsh_stdin.h cmd.h cmd_misc.h -cmd_help.o: cmd_help.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h cmd.h -cmd_history.o: cmd_history.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_if.o: cmd_if.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_getopt.h \ - sqsh_buf.h sqsh_stdin.h sqsh_readline.h cmd.h cmd_misc.h cmd_input.h -cmd_input.o: cmd_input.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_readline.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h -cmd_jobs.o: cmd_jobs.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_kill.o: cmd_kill.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_lock.o: cmd_lock.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h sqsh_global.h sqsh_env.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h cmd.h -cmd_loop.o: cmd_loop.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_getopt.h \ - sqsh_readline.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h -cmd_misc.o: cmd_misc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h cmd.h \ - cmd_misc.h -cmd_read.o: cmd_read.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_getopt.h \ - sqsh_readline.h sqsh_stdin.h cmd.h -cmd_reconnect.o: cmd_reconnect.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_redraw.o: cmd_redraw.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h -cmd_reset.o: cmd_reset.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_return.o: cmd_return.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h sqsh_env.h sqsh_global.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_rpc.o: cmd_rpc.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_getopt.h sqsh_sig.h \ - sqsh_stdin.h cmd.h -cmd_set.o: cmd_set.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_shell.o: cmd_shell.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_varbuf.h sqsh_global.h sqsh_env.h \ - sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_show.o: cmd_show.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_sleep.o: cmd_sleep.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h -cmd_wait.o: cmd_wait.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_stdin.h cmd.h -cmd_warranty.o: cmd_warranty.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_while.o: cmd_while.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_getopt.h sqsh_buf.h sqsh_stdin.h sqsh_readline.h sqsh_tok.h \ - cmd.h cmd_misc.h cmd_input.h -dsp.o: dsp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_error.h sqsh_sig.h -dsp_bcp.o: dsp_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -dsp_csv.o: dsp_csv.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -dsp_conv.o: dsp_conv.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h dsp.h -dsp_desc.o: dsp_desc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_horiz.o: dsp_horiz.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_html.o: dsp_html.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_meta.o: dsp_meta.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h dsp.h -dsp_none.o: dsp_none.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_out.o: dsp_out.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -dsp_pretty.o: dsp_pretty.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_vert.o: dsp_vert.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_x.o: dsp_x.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -sqsh_alias.o: sqsh_alias.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_alias.h sqsh_varbuf.h sqsh_avl.h -sqsh_args.o: sqsh_args.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_args.h -sqsh_avl.o: sqsh_avl.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_avl.h -sqsh_buf.o: sqsh_buf.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_stdin.h sqsh_buf.h -sqsh_cmd.o: sqsh_cmd.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_avl.h sqsh_cmd.h -sqsh_compat.o: sqsh_compat.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_sig.h -sqsh_ctx.o: sqsh_ctx.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_ctx.h sqsh_varbuf.h dsp.h -sqsh_debug.o: sqsh_debug.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h -sqsh_env.o: sqsh_env.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_env.h -sqsh_error.o: sqsh_error.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h -sqsh_expand.o: sqsh_expand.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_varbuf.h sqsh_env.h sqsh_global.h \ - sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_fd.h sqsh_expand.h \ - sqsh_strchr.h sqsh_sig.h -sqsh_fd.o: sqsh_fd.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_sigcld.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ - dsp.h sqsh_func.h sqsh_error.h sqsh_fd.h -sqsh_filter.o: sqsh_filter.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_fd.h sqsh_sig.h sqsh_varbuf.h sqsh_error.h \ - sqsh_filter.h -sqsh_fork.o: sqsh_fork.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_fork.h -sqsh_func.o: sqsh_func.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_avl.h sqsh_func.h -sqsh_getopt.o: sqsh_getopt.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_varbuf.h sqsh_global.h sqsh_env.h \ - sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h -sqsh_global.o: sqsh_global.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -sqsh_history.o: sqsh_history.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_history.h sqsh_varbuf.h -sqsh_init.o: sqsh_init.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h \ - sqsh_readline.h sqsh_stdin.h sqsh_init.h cmd.h var.h alias.h -sqsh_job.o: sqsh_job.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_fd.h sqsh_tok.h sqsh_varbuf.h \ - sqsh_cmd.h sqsh_avl.h sqsh_global.h sqsh_env.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h \ - sqsh_fork.h sqsh_expand.h sqsh_strchr.h sqsh_getopt.h sqsh_sig.h -sqsh_main.o: sqsh_main.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_error.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h \ - sqsh_init.h sqsh_fd.h sqsh_readline.h sqsh_expand.h sqsh_sig.h \ - sqsh_stdin.h cmd.h -sqsh_readline.o: sqsh_readline.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_stdin.h \ - sqsh_readline.h -sqsh_sig.o: sqsh_sig.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_sig.h -sqsh_sigcld.o: sqsh_sigcld.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_sig.h sqsh_sigcld.h -sqsh_stdin.o: sqsh_stdin.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_sigcld.h sqsh_env.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_stdin.h -sqsh_strchr.o: sqsh_strchr.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_strchr.h sqsh_error.h -sqsh_test.o: sqsh_test.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_varbuf.h sqsh_filter.h -sqsh_tok.o: sqsh_tok.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_tok.h sqsh_varbuf.h -sqsh_varbuf.o: sqsh_varbuf.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_varbuf.h sqsh_error.h -var_ctlib.o: var_ctlib.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_fd.h var.h -var_date.o: var_date.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h -var_debug.o: var_debug.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h -var_dsp.o: var_dsp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_error.h sqsh_fd.h var.h -var_hist.o: var_hist.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h -var_misc.o: var_misc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_stdin.h var.h -var_passwd.o: var_passwd.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h var.h -var_readline.o: var_readline.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h var.h -var_thresh.o: var_thresh.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h var.h diff --git a/src/Makefile.in b/src/Makefile.in index 6bac214..93c822a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -3,8 +3,8 @@ # # The following list of sqshrc files will be executed by sqsh upon -# startup. This allows for system-wide defaults to be set in a -# common directory. If you don't want a global sqshrc just comment +# startup. This allows for system-wide defaults to be set in a +# common directory. If you don't want a global sqshrc just comment # out SQSHRC_GLOBAL, below. sysconfdir = @sysconfdir@ @@ -26,13 +26,13 @@ SYBASE_LIBDIR = @SYBASE_LIBDIR@ # word "Guess", then 'configure' didn't have an entry for your operating # system and it took a best guess to figure out which libraries you # need. In either case, there may be problems, so look this line over -# and if it doesn't work, compare it to the libraries located in +# and if it doesn't work, compare it to the libraries located in # $SYBASE/samples/ctlibrary. # # The listings below show suggested libraries for Operating Systems # that frequently fail to be recognized by 'configure': # -# SCO: -lblk -lct -lcs -lcomn -ltcl -ltli -lnsl_s -lintl -m -lsocket +# SCO: -lblk -lct -lcs -lcomn -ltcl -ltli -lnsl_s -lintl -m -lsocket # Dynix: -lblk -lct -lcs -lcomn -ltcl -ltli -lnsl -lintl -lm -lseq # SYBASE_LIBS = @SYBASE_LIBS@ @SYBASE_OS@ @@ -54,7 +54,7 @@ DEF_READLINE = @DEF_READLINE@ READLINE_LIBS = @READLINE_LIBS@ # -# Motif Support - The `configure' motif support logic for sqsh +# Motif Support - The `configure' motif support logic for sqsh # isn't exactly perfected yet. If --with-motif was run, the # following what `configure' guessed at for the location # for your Motif includes and libs. Note that if MOTIF_INCDIR @@ -114,7 +114,7 @@ X_LIBS = @ATHENA_LIBS@ $(MOTIF_LIBS) @X_LIBS@ # # you probably have the bug. First, PLEASE e-mail me (gray@voicenet.com) # and I'll give you a description of what is going on so you can call -# tech support: I am trying to get them to fix the problem, but they +# tech support: I am trying to get them to fix the problem, but they # are moving at a snails pace. Then, when you have done that, un- # comment the following line, which will attempt to install a work- # around for the problem. @@ -133,13 +133,14 @@ X_LIBS = @ATHENA_LIBS@ $(MOTIF_LIBS) @X_LIBS@ # unless you are debugging a problem or are interested in what is # going on under the hood. # -#DEF_DEBUG = -DDEBUG +DEF_DEBUG = @DEF_DEBUG@ # # End of user configuration section. # prefix = @prefix@ +datarootdir = @datarootdir@ src_dir = @srcdir@ exec_prefix = @exec_prefix@ bin_dir = $(exec_prefix)/bin @@ -156,16 +157,15 @@ INSTALL_DATA = $(INSTALL) -c -m 644 INSTALL_MAN = $(src_dir)/autoconf/install-man CC = @CC@ -DEBUG = DEFINES = -DSQSH_RC='${SQSHRC_PATH}' $(DEF_READLINE) \ $(DEF_NOBCP) $(DEF_DEBUG) $(DEF_INSECURE) $(DEF_X11) \ $(DEF_MOTIF) $(DEF_BUGFIX) @DEF_POSIX@ @DEF_AIX_FIX@ INCLUDE_DIRS = $(X_INCDIR) $(MOTIF_INCDIR) $(SYBASE_INCDIR) $(READLINE_INCDIR) LIB_DIRS = $(X_LIBDIR) $(MOTIF_INCDIR) $(SYBASE_LIBDIR) $(READLINE_LIBDIR) -CFLAGS = @CFLAGS@ $(DEBUG) $(DEFINES) $(INCLUDE_DIRS) +CFLAGS = @CFLAGS@ $(DEFINES) $(INCLUDE_DIRS) CPPFLAGS = @CPPFLAGS@ -LDFLAGS = $(DEBUG) $(LIB_DIRS) -LIBS = $(SYBASE_LIBS) $(X_LIBS) $(READLINE_LIBS) @LIBS@ +LDFLAGS = @LDFLAGS@ $(LIB_DIRS) +LIBS = $(SYBASE_LIBS) $(X_LIBS) $(READLINE_LIBS) @LIBS@ @SQSH_PARSE_LIB@ # The follow define information about the components that make up # the actual program. @@ -178,7 +178,7 @@ CMDS = \ cmd_help.o cmd_history.o cmd_if.o cmd_input.o cmd_jobs.o \ cmd_kill.o cmd_lock.o cmd_loop.o cmd_misc.o cmd_read.o \ cmd_reconnect.o cmd_redraw.o cmd_reset.o cmd_return.o cmd_rpc.o \ - cmd_set.o cmd_shell.o cmd_show.o cmd_sleep.o cmd_wait.o \ + cmd_run.o cmd_set.o cmd_shell.o cmd_show.o cmd_sleep.o cmd_wait.o \ cmd_warranty.o cmd_while.o DISPLAYS = \ @@ -192,7 +192,7 @@ VARS = \ CORE = \ sqsh_alias.o sqsh_args.o sqsh_avl.o sqsh_buf.o sqsh_cmd.o \ - sqsh_compat.o sqsh_ctx.o sqsh_debug.o sqsh_env.o sqsh_error.o \ + sqsh_compat.o sqsh_debug.o sqsh_env.o sqsh_error.o \ sqsh_expand.o sqsh_fd.o sqsh_filter.o sqsh_fork.o sqsh_func.o \ sqsh_getopt.o sqsh_global.o sqsh_history.o sqsh_init.o \ sqsh_job.o sqsh_readline.o sqsh_sig.o sqsh_sigcld.o sqsh_stdin.o \ @@ -202,7 +202,7 @@ OBJS = $(CMDS) $(VARS) $(DISPLAYS) $(CORE) MAN_PAGES = sqsh.1 SRCS = $(OBJS:.o=.c) -HEADERS = +HEADERS = $(TARGET) : $(OBJS) sqsh_main.o $(CC) $(LDFLAGS) $(OBJS) sqsh_main.o $(LIBS) -o $@ @@ -223,14 +223,14 @@ realclean : clean distclean : realclean rm -f Makefile config.h core -# +# # The following absolutely disgusting list of dependancies was # automatically generated via 'gcc -MM' # cmd_alias.o: cmd_alias.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ + sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ + sqsh_alias.h dsp.h sqsh_func.h cmd.h cmd_bcp.o: cmd_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ @@ -238,219 +238,221 @@ cmd_bcp.o: cmd_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ cmd_buf.o: cmd_buf.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ - sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_buf.h sqsh_stdin.h cmd.h + sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_buf.h sqsh_stdin.h \ + sqsh_expand.h sqsh_init.h cmd.h cmd_connect.o: cmd_connect.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h \ - sqsh_init.h sqsh_stdin.h cmd.h + sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ + sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ + sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h sqsh_init.h sqsh_sig.h \ + sqsh_stdin.h cmd.h sqsh_expand.h cmd_do.o: cmd_do.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_buf.h \ - sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h \ - cmd_input.h -cmd_echo.o: cmd_echo.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_exit.o: cmd_exit.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h + sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h +cmd_echo.o: cmd_echo.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h cmd.h +cmd_exit.o: cmd_exit.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h cmd.h cmd_for.o: cmd_for.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_buf.h \ - sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h \ - cmd_input.h -cmd_func.o: cmd_func.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_getopt.h sqsh_buf.h sqsh_stdin.h sqsh_readline.h cmd.h \ - cmd_misc.h cmd_input.h + sqsh_readline.h sqsh_getopt.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h +cmd_func.o: cmd_func.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_getopt.h \ + sqsh_buf.h sqsh_stdin.h sqsh_readline.h cmd.h cmd_misc.h cmd_input.h cmd_go.o: cmd_go.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_getopt.h sqsh_buf.h \ sqsh_filter.h sqsh_stdin.h cmd.h cmd_misc.h -cmd_help.o: cmd_help.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h cmd.h +cmd_help.o: cmd_help.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h cmd.h cmd_history.o: cmd_history.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_error.h sqsh_getopt.h sqsh_global.h sqsh_env.h \ + sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h sqsh_expand.h cmd_if.o: cmd_if.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_getopt.h \ sqsh_buf.h sqsh_stdin.h sqsh_readline.h cmd.h cmd_misc.h cmd_input.h cmd_input.o: cmd_input.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_readline.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h -cmd_jobs.o: cmd_jobs.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_kill.o: cmd_kill.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_lock.o: cmd_lock.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h sqsh_global.h sqsh_env.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h cmd.h -cmd_loop.o: cmd_loop.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_getopt.h \ - sqsh_readline.h sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h -cmd_misc.o: cmd_misc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h cmd.h \ - cmd_misc.h -cmd_read.o: cmd_read.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_getopt.h \ - sqsh_readline.h sqsh_stdin.h cmd.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_readline.h \ + sqsh_stdin.h cmd.h cmd_misc.h cmd_input.h +cmd_jobs.o: cmd_jobs.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h cmd.h +cmd_kill.o: cmd_kill.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h +cmd_lock.o: cmd_lock.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_cmd.h sqsh_avl.h sqsh_global.h sqsh_env.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h cmd.h +cmd_loop.o: cmd_loop.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_readline.h sqsh_stdin.h \ + cmd.h cmd_misc.h cmd_input.h +cmd_misc.o: cmd_misc.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_expand.h sqsh_error.h cmd.h cmd_misc.h +cmd_read.o: cmd_read.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_readline.h sqsh_stdin.h \ + cmd.h cmd_reconnect.o: cmd_reconnect.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_redraw.o: cmd_redraw.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h cmd_reset.o: cmd_reset.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_return.o: cmd_return.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_cmd.h sqsh_avl.h sqsh_env.h sqsh_global.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_cmd.h sqsh_avl.h sqsh_env.h sqsh_global.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_rpc.o: cmd_rpc.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_getopt.h sqsh_sig.h \ sqsh_stdin.h cmd.h +cmd_run.o: cmd_run.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h sqsh_getopt.h sqsh_readline.h sqsh_stdin.h \ + cmd.h cmd_misc.h cmd_input.h cmd_set.o: cmd_set.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_shell.o: cmd_shell.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_varbuf.h sqsh_global.h sqsh_env.h \ sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h -cmd_show.o: cmd_show.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h cmd.h +cmd_show.o: cmd_show.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_sleep.o: cmd_sleep.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_cmd.h sqsh_avl.h cmd.h sqsh_varbuf.h -cmd_wait.o: cmd_wait.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_stdin.h cmd.h +cmd_wait.o: cmd_wait.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_stdin.h cmd.h cmd_warranty.o: cmd_warranty.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h cmd.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h cmd.h cmd_while.o: cmd_while.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h \ - sqsh_getopt.h sqsh_buf.h sqsh_stdin.h sqsh_readline.h sqsh_tok.h \ - cmd.h cmd_misc.h cmd_input.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_expand.h sqsh_error.h sqsh_sig.h sqsh_getopt.h \ + sqsh_buf.h sqsh_stdin.h sqsh_readline.h sqsh_tok.h cmd.h cmd_misc.h \ + cmd_input.h +dsp_bcp.o: dsp_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h dsp.o: dsp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_error.h sqsh_sig.h -dsp_bcp.o: dsp_bcp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h +dsp_conv.o: dsp_conv.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h dsp.h dsp_csv.o: dsp_csv.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h -dsp_conv.o: dsp_conv.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h dsp.h -dsp_desc.o: dsp_desc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h +dsp_desc.o: dsp_desc.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h dsp_horiz.o: dsp_horiz.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_html.o: dsp_html.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_meta.o: dsp_meta.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h dsp.h -dsp_none.o: dsp_none.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_out.o: dsp_out.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ + sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ sqsh_alias.h dsp.h sqsh_func.h +dsp_html.o: dsp_html.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h +dsp_meta.o: dsp_meta.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h dsp.h +dsp_none.o: dsp_none.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h +dsp_out.o: dsp_out.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h dsp_pretty.o: dsp_pretty.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_vert.o: dsp_vert.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h -dsp_x.o: dsp_x.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ + sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ sqsh_alias.h dsp.h sqsh_func.h +dsp_vert.o: dsp_vert.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h +dsp_x.o: dsp_x.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_expand.h sqsh_varbuf.h sqsh_global.h sqsh_env.h \ + sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_init.h sqsh_alias.o: sqsh_alias.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_alias.h sqsh_varbuf.h sqsh_avl.h sqsh_args.o: sqsh_args.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_args.h -sqsh_avl.o: sqsh_avl.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_avl.h -sqsh_buf.o: sqsh_buf.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_stdin.h sqsh_buf.h -sqsh_cmd.o: sqsh_cmd.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_avl.h sqsh_cmd.h +sqsh_avl.o: sqsh_avl.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_avl.h +sqsh_buf.o: sqsh_buf.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ + sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ + sqsh_func.h sqsh_error.h sqsh_stdin.h sqsh_buf.h sqsh_readline.h +sqsh_cmd.o: sqsh_cmd.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_avl.h sqsh_cmd.h sqsh_compat.o: sqsh_compat.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_sig.h -sqsh_ctx.o: sqsh_ctx.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_ctx.h sqsh_varbuf.h dsp.h sqsh_debug.o: sqsh_debug.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h -sqsh_env.o: sqsh_env.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_env.h +sqsh_env.o: sqsh_env.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_env.h sqsh_error.o: sqsh_error.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_expand.o: sqsh_expand.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_varbuf.h sqsh_env.h sqsh_global.h \ sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_fd.h sqsh_expand.h \ - sqsh_strchr.h sqsh_sig.h + sqsh_strchr.h sqsh_sig.h sqsh_readline.h sqsh_fd.o: sqsh_fd.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ - sqsh_sigcld.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ - dsp.h sqsh_func.h sqsh_error.h sqsh_fd.h + sqsh_sigcld.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h \ + sqsh_error.h sqsh_fd.h sqsh_filter.o: sqsh_filter.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_fd.h sqsh_sig.h sqsh_varbuf.h sqsh_error.h \ sqsh_filter.h sqsh_fork.o: sqsh_fork.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_fork.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_error.h sqsh_fork.h sqsh_func.o: sqsh_func.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_avl.h sqsh_func.h sqsh_getopt.o: sqsh_getopt.c sqsh_config.h config.h sqsh_compat.h \ @@ -458,34 +460,35 @@ sqsh_getopt.o: sqsh_getopt.c sqsh_config.h config.h sqsh_compat.h \ sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h sqsh_global.o: sqsh_global.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_history.o: sqsh_history.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_history.h sqsh_varbuf.h + sqsh_debug.h sqsh_error.h sqsh_expand.h sqsh_varbuf.h sqsh_global.h \ + sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_init.o: sqsh_init.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h \ - sqsh_readline.h sqsh_stdin.h sqsh_init.h cmd.h var.h alias.h -sqsh_job.o: sqsh_job.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_fd.h sqsh_tok.h sqsh_varbuf.h \ - sqsh_cmd.h sqsh_avl.h sqsh_global.h sqsh_env.h sqsh_job.h sqsh_args.h \ - sqsh_sigcld.h sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h \ - sqsh_fork.h sqsh_expand.h sqsh_strchr.h sqsh_getopt.h sqsh_sig.h + sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ + sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ + sqsh_alias.h dsp.h sqsh_func.h sqsh_expand.h sqsh_readline.h \ + sqsh_stdin.h sqsh_init.h cmd.h var.h alias.h +sqsh_job.o: sqsh_job.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_fd.h sqsh_init.h sqsh_tok.h sqsh_varbuf.h sqsh_cmd.h \ + sqsh_avl.h sqsh_global.h sqsh_env.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_fork.h sqsh_expand.h \ + sqsh_strchr.h sqsh_getopt.h sqsh_sig.h sqsh_main.o: sqsh_main.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_error.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h \ - sqsh_init.h sqsh_fd.h sqsh_readline.h sqsh_expand.h sqsh_sig.h \ - sqsh_stdin.h cmd.h + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_getopt.h sqsh_init.h \ + sqsh_fd.h sqsh_readline.h sqsh_expand.h sqsh_sig.h sqsh_stdin.h cmd.h sqsh_readline.o: sqsh_readline.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_global.h sqsh_env.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_stdin.h \ - sqsh_readline.h -sqsh_sig.o: sqsh_sig.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_sig.h + sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_expand.h sqsh_varbuf.h \ + sqsh_global.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h \ + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_init.h \ + sqsh_readline.h sqsh_stdin.h sqsh_parser/sqsh_parser.h +sqsh_sig.o: sqsh_sig.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_sig.h sqsh_sigcld.o: sqsh_sigcld.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_error.h sqsh_sig.h sqsh_sigcld.h sqsh_stdin.o: sqsh_stdin.c sqsh_config.h config.h sqsh_compat.h \ @@ -496,37 +499,39 @@ sqsh_strchr.o: sqsh_strchr.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_strchr.h sqsh_error.h sqsh_test.o: sqsh_test.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_varbuf.h sqsh_filter.h -sqsh_tok.o: sqsh_tok.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_error.h sqsh_tok.h sqsh_varbuf.h +sqsh_tok.o: sqsh_tok.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_error.h sqsh_tok.h sqsh_varbuf.h sqsh_varbuf.o: sqsh_varbuf.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_varbuf.h sqsh_error.h var_ctlib.o: var_ctlib.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h sqsh_fd.h var.h -var_date.o: var_date.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h + sqsh_debug.h sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_error.h sqsh_fd.h var.h sqsh_expand.h +var_date.o: var_date.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h var.h var_debug.o: var_debug.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ - sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h + sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h sqsh_avl.h \ + sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ + sqsh_alias.h dsp.h sqsh_func.h var.h var_dsp.o: var_dsp.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ sqsh_global.h sqsh_env.h sqsh_cmd.h sqsh_avl.h sqsh_job.h sqsh_args.h \ sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h dsp.h \ sqsh_func.h sqsh_error.h sqsh_fd.h var.h -var_hist.o: var_hist.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h \ +var_hist.o: var_hist.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_env.h sqsh_error.h sqsh_global.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h var.h +var_misc.o: var_misc.c sqsh_config.h config.h sqsh_compat.h sqsh_debug.h \ + sqsh_env.h sqsh_error.h sqsh_stdin.h var.h sqsh_global.h sqsh_cmd.h \ sqsh_avl.h sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h \ - sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h var.h -var_misc.o: var_misc.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_stdin.h var.h + sqsh_history.h sqsh_alias.h dsp.h sqsh_func.h sqsh_fd.h sqsh_expand.h var_passwd.o: var_passwd.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h \ - sqsh_job.h sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h \ - sqsh_alias.h dsp.h sqsh_func.h sqsh_error.h var.h + sqsh_debug.h sqsh_env.h sqsh_global.h sqsh_cmd.h sqsh_avl.h sqsh_job.h \ + sqsh_args.h sqsh_sigcld.h sqsh_varbuf.h sqsh_history.h sqsh_alias.h \ + dsp.h sqsh_func.h sqsh_error.h var.h var_readline.o: var_readline.c sqsh_config.h config.h sqsh_compat.h \ - sqsh_debug.h sqsh_env.h sqsh_error.h var.h + sqsh_debug.h sqsh_env.h sqsh_error.h sqsh_readline.h var.h var_thresh.o: var_thresh.c sqsh_config.h config.h sqsh_compat.h \ sqsh_debug.h sqsh_env.h sqsh_error.h var.h @@ -96,6 +96,10 @@ int cmd_return _ANSI_ARGS(( int, char** )) ; int cmd_break _ANSI_ARGS(( int, char** )) ; int cmd_for _ANSI_ARGS(( int, char** )) ; int cmd_snace _ANSI_ARGS(( int, char** )) ; +int cmd_run _ANSI_ARGS(( int, char** )) ; +int cmd_lcd _ANSI_ARGS(( int, char** )) ; /* sqsh-2.5 local change dir */ +int cmd_pwd _ANSI_ARGS(( int, char** )) ; /* sqsh-2.5 show current dir */ +int cmd_ls _ANSI_ARGS(( int, char** )) ; /* sqsh-2.5 list files in current dir */ #ifdef SQSH_INIT /* @@ -164,6 +168,10 @@ static cmd_entry_t sg_cmd_entry[] = { { "\\buf-append",NULL, cmd_buf_append }, { "\\buf-del", NULL, cmd_buf_del }, /* sqsh-2.1.6 feature */ { "\\snace", NULL, cmd_snace }, /* sqsh-2.1.7 */ + { "\\run", NULL, cmd_run }, /* sqsh-2.5 */ + { "\\lcd", NULL, cmd_lcd }, /* sqsh-2.5 */ + { "\\pwd", NULL, cmd_pwd }, /* sqsh-2.5 */ + { "\\ls", NULL, cmd_ls }, /* sqsh-2.5 */ { ":r", NULL, cmd_buf_load }, { "vi", NULL, cmd_buf_edit }, { "emacs", NULL, cmd_buf_edit }, diff --git a/src/cmd_bcp.c b/src/cmd_bcp.c index 0c56b76..9f50f34 100644 --- a/src/cmd_bcp.c +++ b/src/cmd_bcp.c @@ -24,6 +24,7 @@ */ #include <stdio.h> #include <ctpublic.h> +#include <ctype.h> #include <bkpublic.h> #include "sqsh_config.h" #include "sqsh_global.h" @@ -39,7 +40,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_bcp.c,v 1.10 2010/03/28 11:46:05 mpeppler Exp $"; +static char RCS_Id[] = "$Id: cmd_bcp.c,v 1.21 2014/04/04 08:22:38 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -54,12 +55,18 @@ USE(RCS_Id) /* * sg_interrupted: This variable is set by the bcp_signal() signal - * handler and is to be polled periodically to determine if + * handler and is to be polled periodically to determine if * a signal has been recieved. */ static int sg_interrupted = False; /* + * sg_error: This variable is set by the callback functions and is + * used when the init command returns an error. + */ +static int sg_error = False; + +/* * sg_bcp_connection: This variable is used by the signal handler * to determine which connection needs to be canceled. */ @@ -112,20 +119,29 @@ static void bcp_signal _ANSI_ARGS(( int, void* )); static bcp_data_t* bcp_data_bind _ANSI_ARGS(( CS_COMMAND*, CS_INT )); static CS_INT bcp_data_xfer _ANSI_ARGS(( bcp_data_t*, CS_COMMAND*, CS_BLKDESC* )); static void bcp_data_destroy _ANSI_ARGS(( bcp_data_t* )); -static CS_RETCODE bcp_server_cb +static CS_RETCODE bcp_server_cb _ANSI_ARGS(( CS_CONTEXT*, CS_CONNECTION*, CS_SERVERMSG* )) -#if defined(_CYGWIN32_) +#if defined(__CYGWIN__) __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ +#endif /* __CYGWIN__ */ ; static CS_RETCODE bcp_client_cb _ANSI_ARGS(( CS_CONTEXT*, CS_CONNECTION*, CS_CLIENTMSG* )) -#if defined(_CYGWIN32_) +#if defined(__CYGWIN__) __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ +#endif /* __CYGWIN__ */ ; +#if defined(CS_SSLVALIDATE_CB) +static CS_RETCODE validate_srvname_cb + _ANSI_ARGS(( CS_VOID*, CS_SSLCERT*, CS_INT, CS_INT )) +#if defined(__CYGWIN__) + __attribute__ ((stdcall)) +#endif /* __CYGWIN__ */ + ; +#endif + int cmd_bcp( argc, argv ) int argc ; char *argv[] ; @@ -144,6 +160,8 @@ int cmd_bcp( argc, argv ) extern char* sqsh_optarg; /* Value of option */ int opt; /* Current option */ char *bcp_table; /* Table to bcp into */ + char *bcp_partition; /* Partition name to bcp into */ + int bcp_slicenum; /* Partition number to bcp into */ char *cmd_sql; /* SQL command to send to server */ int rows_in_batch; /* Rows processed in batch */ int total_rows; /* Total rows processing */ @@ -157,6 +175,7 @@ int cmd_bcp( argc, argv ) CS_BOOL bcp_on = CS_TRUE; /* Flag to turn on bulk login */ CS_INT i; CS_INT con_status; + char *cp; /* * The following variables need to be initialized to check if @@ -183,6 +202,17 @@ int cmd_bcp( argc, argv ) int batchsize = -1; /* Copy all rows in one batch */ int have_error = False; CS_BOOL have_identity = CS_FALSE; +#if defined (CS_NOCHARSETCNV_REQD) && defined (BLK_CONV) + CS_BOOL char_convert = CS_FALSE; /* Used with -T option (transit) */ + CS_BOOL transit = CS_FALSE; /* Disable client character conversion */ +#endif + + /* + * sqsh-2.1.9 - Feature BCP execute an initialization command + */ + char *init_cmd = NULL; /* BCP init command option */ + CS_COMMAND *bcp_cmd_init = NULL; /* Command sent to server */ + CS_RETCODE retcode; /* return code */ /* * Retrieve value of variables used to configure the connection. @@ -199,16 +229,16 @@ int cmd_bcp( argc, argv ) env_get( g_env, "hostname", &hostname ); env_get( g_env, "packet_size", &packet_size ); - while ((opt = sqsh_getopt( argc, argv, "A:b:I:J:m:NP;S:U:Xz:" )) != EOF) + while ((opt = sqsh_getopt( argc, argv, "A:b:I:i:J:m:NP;S:TU:Xz:" )) != EOF) { - switch (opt) + switch (opt) { case 'A': packet_size = sqsh_optarg; break; case 'b': - if ((batchsize = atoi(sqsh_optarg)) <= 0) + if ((batchsize = atoi(sqsh_optarg)) <= 0) { fprintf(stderr, "\\bcp: -b: Invalid value '%s'\n", sqsh_optarg); return CMD_FAIL; @@ -223,18 +253,22 @@ int cmd_bcp( argc, argv ) } break; + case 'i' : + init_cmd = sqsh_optarg; + break; + case 'J' : charset = sqsh_optarg; break; case 'm': - if ((maxerrors = atoi(sqsh_optarg)) <= 0) + if ((maxerrors = atoi(sqsh_optarg)) <= 0) { fprintf(stderr, "\\bcp: -m: Invalid value '%s'\n", sqsh_optarg); return CMD_FAIL; } break; - + case 'N': have_identity = CS_TRUE; break; @@ -247,7 +281,16 @@ int cmd_bcp( argc, argv ) server = sqsh_optarg; break; - case 'U' : + case 'T' : +#if defined (CS_NOCHARSETCNV_REQD) && defined (BLK_CONV) + transit = CS_TRUE; +#else + fprintf(stderr, "\\bcp: -T: Transit option is not supported by bulkcopy library\n"); + fprintf(stderr, "\\bcp: -T: Parameter will be ignored\n"); +#endif + break; + + case 'U' : username = sqsh_optarg; break; @@ -267,15 +310,15 @@ int cmd_bcp( argc, argv ) /* * If there isn't a table name left on the command line, or an - * invalid argument was supplied, then print out usage + * invalid argument was supplied, then print out usage * information. */ - if ((argc - sqsh_optind) != 1 || have_error) + if ((argc - sqsh_optind) != 1 || have_error) { - fprintf(stderr, - "Use: \\bcp [-A packsetsize] [-b batchsize] [-I interfaces]\n" + fprintf(stderr, + "Use: \\bcp [-A packsetsize] [-b batchsize] [-I interfaces] [-i initcmd]\n" " [-J charset] [-m maxerrors] [-N] [-P password]\n" - " [-S server] [-U username] [-X] [-z language] table_name\n"); + " [-S server] [-T] [-U username] [-X] [-z language] table_name\n"); return CMD_FAIL; } @@ -285,12 +328,21 @@ int cmd_bcp( argc, argv ) bcp_table = argv[sqsh_optind]; /* + * sqsh-2.2.0 - Feature enable BCP_IN into a specific partition of a partitioned table + */ + if ((bcp_partition = strchr(bcp_table, (int) ':')) != NULL) + { + *bcp_partition++ = '\0'; + } + + /* * Now, install our signal handlers. At this point, all code should * perform a goto {return_fail or return_interrupt} to return an error * condition. This is important in order to clean up the signal * handlers and various other data structures created. */ sg_interrupted = False; + sg_error = False; sg_bcp_connection = NULL; sig_save(); @@ -302,20 +354,20 @@ int cmd_bcp( argc, argv ) * remote database (that we are bcp'ing too), lets launch our * query and see if it is valid. */ - if (expand == NULL || *expand != '0') + if (expand == NULL || *expand != '0') { /* * Temporarily create a buffer in which to store the expanded * SQL buffer. */ - if ((exp_buf = varbuf_create(512)) == NULL) + if ((exp_buf = varbuf_create(512)) == NULL) { fprintf(stderr, "\\bcp: varbuf_create: %s\n", sqsh_get_errstr()); goto return_fail; } if (sqsh_expand( varbuf_getstr( g_sqlbuf ), exp_buf, - EXP_STRIPESC|EXP_COMMENT|EXP_COLUMNS ) == False) + EXP_STRIPESC|EXP_COMMENT|EXP_COLUMNS ) == False) { fprintf(stderr, "\\bcp: sqsh_expand: %s\n", sqsh_get_errstr()); goto return_fail; @@ -323,7 +375,7 @@ int cmd_bcp( argc, argv ) cmd_sql = varbuf_getstr( exp_buf ); - } + } else { cmd_sql = varbuf_getstr( g_sqlbuf ); @@ -342,6 +394,27 @@ int cmd_bcp( argc, argv ) /*-- Find the appropriate BLK_VERSION_xxx value --*/ /*-- sqsh-2.1.7 - Make it compile with freetds-0.82 --*/ + /*-- sqsh-2.1.9 - Added version BLK_VERSION_157 --*/ + /*-- sqsh-2.5.16 - Added version BLK_VERSION_160 --*/ +#if defined(CS_VERSION_160) + if(blk_ver == -1 && g_cs_ver == CS_VERSION_160) { +#if defined(BLK_VERSION_160) + blk_ver = BLK_VERSION_160; +#else + blk_ver = BLK_VERSION_110; +#endif + } +#endif +#if defined(CS_VERSION_157) + if(blk_ver == -1 && g_cs_ver == CS_VERSION_157) { +#if defined(BLK_VERSION_157) + blk_ver = BLK_VERSION_157; +#else + blk_ver = BLK_VERSION_110; +#endif + } +#endif + #if defined(CS_VERSION_155) if(blk_ver == -1 && g_cs_ver == CS_VERSION_155) { #if defined(BLK_VERSION_155) @@ -402,6 +475,9 @@ int cmd_bcp( argc, argv ) goto return_fail; } + /* sqsh-2.5 - Feature p2f, reset g_p2fc before a new batch is started */ + g_p2fc = 0; + /*-- Send command to server --*/ if (ct_send( bcp_cmd ) != CS_SUCCEED) { @@ -411,7 +487,7 @@ int cmd_bcp( argc, argv ) if (sg_interrupted) goto return_interrupt; - + /* * If we have reached this point, then everything looks like it * went OK, so it is now time to create a new connection to the @@ -441,7 +517,7 @@ int cmd_bcp( argc, argv ) CS_SERVERMSG_CB, /* Type */ (CS_VOID*)bcp_server_cb /* Callback Pointer */ ) != CS_SUCCEED) - goto return_fail; + goto return_fail; /*-- Set Bulk Login --*/ if (ct_con_props( bcp_con, /* Connection */ @@ -450,7 +526,7 @@ int cmd_bcp( argc, argv ) (CS_VOID*)&bcp_on, /* Buffer */ CS_UNUSED, /* Buffer Lenth */ (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { fprintf( stderr, "\\bcp: Unable to mark connection for BCP\n" ); goto return_fail; @@ -463,9 +539,9 @@ int cmd_bcp( argc, argv ) (CS_VOID*)username, /* Buffer */ CS_NULLTERM, /* Buffer Lenth */ (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to set username to '%s' for BCP connection\n", username ); goto return_fail; @@ -478,7 +554,7 @@ int cmd_bcp( argc, argv ) (CS_VOID*)password, /* Buffer */ (password == NULL)?CS_UNUSED:CS_NULLTERM, (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { fprintf( stderr, "\\bcp: Unable to set password BCP connection\n" ); goto return_fail; @@ -491,9 +567,9 @@ int cmd_bcp( argc, argv ) (CS_VOID*)"sqsh-bcp", /* Buffer */ CS_NULLTERM, /* Buffer Lenth */ (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to set appname to 'sqsh-bcp' for BCP connection\n" ); goto return_fail; } @@ -501,14 +577,14 @@ int cmd_bcp( argc, argv ) /*-- Hostname --*/ if (hostname != NULL && *hostname != '\0') { if (ct_con_props( bcp_con, /* 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) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to set hostname to '%s' for BCP connection\n", hostname ); goto return_fail; @@ -519,15 +595,15 @@ int cmd_bcp( argc, argv ) if (packet_size != NULL) { i = atoi(packet_size); if (ct_con_props( bcp_con, /* 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) { - fprintf( stderr, - "\\bcp: Unable to set packetsize to %d for BCP connection\n", + fprintf( stderr, + "\\bcp: Unable to set packetsize to %d for BCP connection\n", (int)i ); goto return_fail; } @@ -537,18 +613,61 @@ int cmd_bcp( argc, argv ) if (encryption != NULL && *encryption == '1') { i = CS_TRUE; if (ct_con_props( bcp_con, /* 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) + { + fprintf( stderr, + "\\bcp: Unable to set password encryption for BCP connection\n" ); + goto return_fail; + } + +#if defined (CS_SEC_EXTENDED_ENCRYPTION) + /* + * sqsh-2.1.9: Enable extended password encryption to be able to + * connect to ASE servers with 'net password encryption reqd' + * configured to 2 (RSA). + */ + if (ct_con_props( bcp_con, /* Connection */ + CS_SET, /* Action */ + CS_SEC_EXTENDED_ENCRYPTION, /* Property */ + (CS_VOID*)&i, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) + { + fprintf( stderr, + "\\bcp: Unable to set extended password encryption for BCP connection\n" ); + goto return_fail; + } +#endif + } + +#if defined (CS_NOCHARSETCNV_REQD) && defined (BLK_CONV) + /* + * sqsh-2.2.0 - Disable character set conversion by client + * when in transit bulk transfer is requested (-T option) + */ + if (transit == CS_TRUE) + { + char_convert = CS_TRUE; + if (ct_con_props( bcp_con, /* Connection */ + CS_SET, /* Action */ + CS_NOCHARSETCNV_REQD, /* Property */ + (CS_VOID*)&char_convert, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) { - fprintf( stderr, - "\\bcp: Unable to set enable encryption for BCP connection\n" ); + fprintf( stderr, + "\\bcp: Unable to set CS_NOCHARSETCONV_REQD for BCP connection\n" ); goto return_fail; } } +#endif /* * The following section initializes all locale type information. @@ -557,7 +676,7 @@ int cmd_bcp( argc, argv ) */ if (cs_loc_alloc( g_context, &bcp_locale ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to allocate locale for BCP connection\n" ); goto return_fail; } @@ -565,14 +684,14 @@ int cmd_bcp( argc, argv ) /*-- Initialize --*/ if (cs_locale( g_context, /* Context */ CS_SET, /* Action */ - bcp_locale, /* Locale Structure */ + bcp_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) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to initialize locale for BCP connection\n" ); goto return_fail; } @@ -582,13 +701,13 @@ int cmd_bcp( argc, argv ) if (cs_locale( g_context, /* Context */ CS_SET, /* Action */ bcp_locale, /* Locale Structure */ - CS_SYB_LANG, /* Property */ - (CS_CHAR*)language, /* Buffer */ - CS_NULLTERM, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SYB_LANG, /* Property */ + (CS_CHAR*)language, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to set language to '%s' for BCP connection\n", language ); goto return_fail; @@ -600,13 +719,13 @@ int cmd_bcp( argc, argv ) if (cs_locale( g_context, /* Context */ CS_SET, /* Action */ bcp_locale, /* Locale Structure */ - CS_SYB_CHARSET, /* Property */ - (CS_CHAR*)charset, /* Buffer */ - CS_NULLTERM, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SYB_CHARSET, /* Property */ + (CS_CHAR*)charset, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "\\bcp: Unable to set charset to '%s' for BCP connection\n", charset ); goto return_fail; @@ -615,17 +734,51 @@ int cmd_bcp( argc, argv ) /*-- Locale Property --*/ if (ct_con_props( bcp_con, /* Connection */ - CS_SET, /* Action */ - CS_LOC_PROP, /* Property */ - (CS_VOID*)bcp_locale, /* Buffer */ - CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL /* Output Length */ - ) != CS_SUCCEED) + CS_SET, /* Action */ + CS_LOC_PROP, /* Property */ + (CS_VOID*)bcp_locale, /* Buffer */ + CS_UNUSED, /* Buffer Length */ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) { fprintf( stderr, "\\bcp: Unable to set locale for BCP connection\n" ); goto return_fail; } +#if defined(CS_SERVERADDR) && defined(CS_TDS_50) + if ( server != NULL && (cp = strchr(server, ':')) != NULL ) + { + char *cp2; + + *cp = ' '; + if ( (cp2 = strchr(cp+1, ':')) != NULL) /* Optional filter specified? */ + *cp2 = ' '; + + if (ct_con_props( bcp_con, + CS_SET, + CS_SERVERADDR, + (CS_VOID*)server, + CS_NULLTERM, + (CS_INT*)NULL + ) != CS_SUCCEED) + goto return_fail; + + if (cp2 != NULL) + *cp2 = '\0'; /* Remove optional filter from the servername */ + *cp = ':'; /* Put a ':' back into the display servername */ + +#if defined(CS_SSLVALIDATE_CB) + if (ct_callback( g_context, /* Context */ + (CS_CONNECTION*)NULL, /* Connection */ + CS_SET, /* Action */ + CS_SSLVALIDATE_CB, /* Type */ + (CS_VOID*)validate_srvname_cb /* Callback Pointer */ + ) != CS_SUCCEED) + goto return_fail; +#endif + } +#endif + /*-- Now, connect --*/ if (ct_connect( bcp_con, server, @@ -662,10 +815,37 @@ int cmd_bcp( argc, argv ) } } #endif /* CTLIB_SIGPOLL_BUG */ - + /*-- Inform signal handler of connection --*/ sg_bcp_connection = bcp_con; + /* + * sqsh-2.1.9 - Feature BCP execute an initialization command + * Process the initialization command provided in init_cmd + */ + if (init_cmd != NULL) + { + if ((retcode = ct_cmd_alloc(bcp_con, &bcp_cmd_init)) != CS_SUCCEED || sg_error == True) + { + fprintf( stderr, "\\bcp: ct_cmd_alloc failed. (retcode=%d, sg_error=%d)\n", (int) retcode, sg_error ); + goto return_fail; + } + + if ((retcode = ct_command(bcp_cmd_init, CS_LANG_CMD, init_cmd, CS_NULLTERM, CS_UNUSED) != CS_SUCCEED) || + sg_error == True) + { + fprintf( stderr, "\\bcp: ct_command() for init_cmd failed. (retcode=%d, sg_error=%d)\n", + (int) retcode, sg_error); + goto return_fail; + } + + if ( dsp_cmd (stdout, bcp_cmd_init, init_cmd, 0) != DSP_SUCCEED || sg_error == True) + { + fprintf( stderr, "\\bcp: Execution of initialization command failed.\n"); + goto return_fail; + } + } + /*-- Allocate a block descriptor --*/ DBG(sqsh_debug(DEBUG_BCP, "bcp: blk_alloc(blk_ver)\n");) @@ -674,7 +854,7 @@ int cmd_bcp( argc, argv ) fprintf( stderr, "\\bcp: Unable to allocate bulk descriptor\n" ); goto return_fail; } - + /* * Configure whether or not this connection is to contain the * value for the identity column in a result set. We default @@ -685,10 +865,10 @@ int cmd_bcp( argc, argv ) if (blk_props( bcp_desc, /* Descriptor */ CS_SET, /* Action */ BLK_IDENTITY, /* Property */ - (CS_VOID*)&have_identity, /* Buffer */ - CS_UNUSED, /* Buffer Length*/ + (CS_VOID*)&have_identity, /* Buffer */ + CS_UNUSED, /* Buffer Length*/ (CS_INT*)NULL /* Output Length */ - ) == CS_FAIL) + ) != CS_SUCCEED) { fprintf( stderr, "\\bcp: Unable to set BLK_IDENTITY option to %s\n", have_identity == CS_TRUE ? "CS_TRUE" : "CS_FALSE" ); @@ -696,11 +876,79 @@ int cmd_bcp( argc, argv ) } } +#if defined (CS_NOCHARSETCNV_REQD) && defined (BLK_CONV) + /* + * sqsh-2.2.0 - Disable character set conversion by client + * when in transit bulk transfer is requested (-T option) + */ + if (transit == CS_TRUE) + { + char_convert = CS_FALSE; + if (blk_props( bcp_desc, /* Descriptor */ + CS_SET, /* Action */ + BLK_CONV, /* Property */ + (CS_VOID*)&char_convert, /* Buffer */ + CS_UNUSED, /* Buffer Length*/ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) + { + fprintf( stderr, "\\bcp: Unable to set BLK_CONV option to CS_FALSE\n"); + goto return_fail; + } + } +#endif + + /* + * sqsh-2.2.0 - Feature enable BCP_IN into a specific partition of a partitioned table + */ + if (bcp_partition != NULL) + { + if (isdigit( (int) *bcp_partition)) + { + bcp_slicenum = atoi (bcp_partition); +#if defined (BLK_SLICENUM) + if (blk_props( bcp_desc, /* Descriptor */ + CS_SET, /* Action */ + BLK_SLICENUM, /* Property */ + (CS_VOID*)&bcp_slicenum, /* Buffer */ + CS_UNUSED, /* Buffer Length*/ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) + { + fprintf( stderr, "\\bcp: Unable to set BLK_SLICENUM option\n"); + goto return_fail; + } +#else + fprintf(stderr, "\\bcp: The build version of Bulk Library does not (fully) support table partitioning.\n"); + fprintf(stderr, "\\bcp: The specified slice number '%d' will be ignored.\n", bcp_slicenum); +#endif + } + else + { +#if defined (BLK_PARTITION) + if (blk_props( bcp_desc, /* Descriptor */ + CS_SET, /* Action */ + BLK_PARTITION, /* Property */ + (CS_VOID*)bcp_partition, /* Buffer */ + strlen(bcp_partition), /* Buffer Length*/ + (CS_INT*)NULL /* Output Length */ + ) != CS_SUCCEED) + { + fprintf( stderr, "\\bcp: Unable to set BLK_PARTITION option\n"); + goto return_fail; + } +#else + fprintf(stderr, "\\bcp: The build version of Bulk Library does not (fully) support table partitioning.\n"); + fprintf(stderr, "\\bcp: The specified partition name '%s' will be ignored.\n", bcp_partition); +#endif + } + } + /*-- Initialize the bulk copy --*/ DBG(sqsh_debug(DEBUG_BCP, "bcp: blk_init(CS_BLK_IN,'%s',%d)\n", bcp_table, strlen(bcp_table));) - if (blk_init( bcp_desc, CS_BLK_IN, bcp_table, + if (blk_init( bcp_desc, CS_BLK_IN, bcp_table, strlen(bcp_table) ) != CS_SUCCEED) { fprintf( stderr, "\\bcp: Unable to initialize bulk copy on table '%s'\n", @@ -709,7 +957,7 @@ int cmd_bcp( argc, argv ) } fprintf(stderr, "\nStarting copy...\n" ); - + /* * Allrightythen. We have already sent the command to retrieve * data through g_dbproc, and have succesfully created bcp_dbproc @@ -724,7 +972,7 @@ int cmd_bcp( argc, argv ) { if (sg_interrupted) goto return_interrupt; - + if (return_code != CS_SUCCEED) break; @@ -742,8 +990,8 @@ int cmd_bcp( argc, argv ) if ((bcp_dat = bcp_data_bind( bcp_cmd, result_type )) == NULL) goto return_fail; - while ((return_code = - bcp_data_xfer( bcp_dat, + while ((return_code = + bcp_data_xfer( bcp_dat, bcp_cmd, bcp_desc )) != CS_END_DATA) { @@ -790,18 +1038,18 @@ int cmd_bcp( argc, argv ) } } /* while (bcp_data_xfer()) */ break; - + case CS_PARAM_RESULT: case CS_STATUS_RESULT: case CS_COMPUTE_RESULT: - while ((return_code = ct_fetch( bcp_cmd, CS_UNUSED, CS_UNUSED, + while ((return_code = ct_fetch( bcp_cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &nrows )) == CS_SUCCEED); - + if (return_code != CS_END_DATA) { fprintf( stderr, "\\bcp: Error discarding extraneous result sets\n" ); - + goto return_fail; } break; @@ -812,7 +1060,7 @@ int cmd_bcp( argc, argv ) } - if (rows_in_batch > 0) + if (rows_in_batch > 0) { DBG(sqsh_debug(DEBUG_BCP, "bcp: FINAL: blk_done(CS_BLK_BATCH)\n");) if (blk_done( bcp_desc, @@ -825,9 +1073,9 @@ int cmd_bcp( argc, argv ) if (sg_interrupted) goto return_interrupt; - if (nrows != rows_in_batch) + if (nrows != rows_in_batch) { - if (++nerrors == maxerrors) + if (++nerrors == maxerrors) goto return_fail; } total_rows += nrows; @@ -840,11 +1088,11 @@ int cmd_bcp( argc, argv ) goto return_fail; gettimeofday( &tv_end, NULL ); - + if (rows_in_batch != 0) fprintf(stderr,"Batch successfully bulk-copied to SQL Server\n"); - fprintf( stderr, "\n%d row%s copied.\n", total_rows, + fprintf( stderr, "\n%d row%s copied.\n", total_rows, (total_rows != 1) ? "s" : "" ); /* add check for non-zero number of rows passed to avoid @@ -852,11 +1100,11 @@ int cmd_bcp( argc, argv ) patch by Onno van der Linden */ if(total_rows > 0) { secs = ELAPSED_SEC(tv_start,tv_end); - fprintf( stderr, + fprintf( stderr, "Clock Time (sec.): Total = %-.4f Avg = %-.4f (%.2f rows per sec.)\n", secs, secs / (double)total_rows, (double)total_rows / secs ); } - + return_code = CMD_RESETBUF; goto leave; @@ -887,7 +1135,7 @@ return_fail: /*-- If connected, disconnect --*/ if (con_status == CS_CONSTAT_CONNECTED) - { + { if (bcp_desc != NULL) { DBG(sqsh_debug(DEBUG_ERROR, "bcp: Cancelling bcp batch.\n");) @@ -898,7 +1146,8 @@ return_fail: ct_cancel( bcp_con, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); DBG(sqsh_debug(DEBUG_ERROR, "bcp: Closing bcp connection.\n");) - ct_close( bcp_con, CS_FORCE_CLOSE ); + if (ct_close( bcp_con, CS_UNUSED ) != CS_SUCCEED) + ct_close( bcp_con, CS_FORCE_CLOSE ); } ct_con_drop( bcp_con ); @@ -940,23 +1189,27 @@ leave: if (bcp_cmd != NULL) ct_cmd_drop( bcp_cmd ); - + + if (bcp_cmd_init != NULL) + ct_cmd_drop( bcp_cmd_init ); + if (bcp_desc != NULL) { DBG(sqsh_debug(DEBUG_BCP, "bcp: blk_drop()\n");) blk_drop( bcp_desc ); } - + if (bcp_con != NULL) { - ct_close( bcp_con, CS_FORCE_CLOSE ); + if (ct_close( bcp_con, CS_UNUSED ) != CS_SUCCEED) + ct_close( bcp_con, CS_FORCE_CLOSE ); ct_con_drop( bcp_con ); } if (bcp_locale != NULL) cs_loc_drop( g_context, bcp_locale ); - sig_restore(); + sig_restore(); return return_code; } @@ -984,7 +1237,7 @@ static bcp_data_t* bcp_data_bind ( cmd, result_type ) d = (bcp_data_t*)calloc( 1, sizeof( bcp_data_t ) ); c = (bcp_col_t*)calloc( ncols, sizeof( bcp_col_t ) ); - if (d == NULL || c == NULL) + if (d == NULL || c == NULL) { fprintf( stderr, "bcp_data_bind: Memory allocation failure.\n" ); if (d != NULL) @@ -999,9 +1252,9 @@ static bcp_data_t* bcp_data_bind ( cmd, result_type ) d->d_ncols = ncols; d->d_cols = c; - for (i = 0; i < ncols; i++) + for (i = 0; i < ncols; i++) d->d_cols[i].c_data = NULL; - + for (i = 0; i < ncols; i++) { c = &d->d_cols[i]; @@ -1010,9 +1263,9 @@ static bcp_data_t* bcp_data_bind ( cmd, result_type ) c->c_nullind = 0; /*-- Get description for column --*/ - if (ct_describe( cmd, i+1, &c->c_format ) != CS_SUCCEED) + if (ct_describe( cmd, i+1, &c->c_format ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "bcp_data_bind: Unable to fetch column %d description\n", (int) i+1 ); bcp_data_destroy( d ); @@ -1029,14 +1282,14 @@ static bcp_data_t* bcp_data_bind ( cmd, result_type ) /*-- Bind to the data space --*/ if (ct_bind( cmd, /* Command */ - i + 1, /* Item */ - &c->c_format, /* Format */ - (CS_VOID*)c->c_data, /* Buffer */ - (CS_INT*)&c->c_len, /* Data Copied */ - &c->c_nullind /* NULL Indicator */ - ) != CS_SUCCEED) + i + 1, /* Item */ + &c->c_format, /* Format */ + (CS_VOID*)c->c_data, /* Buffer */ + (CS_INT*)&c->c_len, /* Data Copied */ + &c->c_nullind /* NULL Indicator */ + ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "bcp_data_bind: Unable to bind column %d\n", (int) i+1 ); bcp_data_destroy( d ); @@ -1062,7 +1315,7 @@ static CS_INT bcp_data_xfer( d, cmd, blkdesc ) CS_UNUSED, /* Offset */ CS_UNUSED, /* Option */ &nrows ); - + if (return_code != CS_SUCCEED) { return return_code; @@ -1094,14 +1347,14 @@ static CS_INT bcp_data_xfer( d, cmd, blkdesc ) c->c_prevnullind = c->c_nullind; if (blk_bind( blkdesc, /* Block Descriptor */ - i + 1, /* Column Number */ - &c->c_format, /* Data Format */ - (CS_VOID*)c->c_data, /* Buffer */ - &c->c_len, /* Buffer Length */ - &c->c_nullind ) != CS_SUCCEED) + i + 1, /* Column Number */ + &c->c_format, /* Data Format */ + (CS_VOID*)c->c_data, /* Buffer */ + &c->c_len, /* Buffer Length */ + &c->c_nullind ) != CS_SUCCEED) { - fprintf( stderr, - "bcp_data_xfer: Unable to bind results for column %d\n", + fprintf( stderr, + "bcp_data_xfer: Unable to bind results for column %d\n", (int) i+1 ); return CS_FAIL; } @@ -1111,7 +1364,7 @@ static CS_INT bcp_data_xfer( d, cmd, blkdesc ) DBG(sqsh_debug(DEBUG_BCP, "bcp: blk_rowxfer()\n");) if (blk_rowxfer( blkdesc ) != CS_SUCCEED) { - fprintf( stderr, + fprintf( stderr, "bcp_data_xfer: Unable to transfer row to remote SQL Server\n" ); return CS_FAIL; } @@ -1183,7 +1436,7 @@ static CS_RETCODE bcp_server_cb (ctx, con, msg) * Ignore "database changed", or "language changed" messages from * the server. */ - if( msg->msgnumber == 5701 || /* database context change */ + if( msg->msgnumber == 5701 || /* database context change */ msg->msgnumber == 5703 || /* language changed */ msg->msgnumber == 5704 ) /* charset changed */ { @@ -1196,12 +1449,12 @@ static CS_RETCODE bcp_server_cb (ctx, con, msg) * If the severity is something other than 0 or the msg number is * 0 (user informational messages). */ - if (msg->severity >= 0 || msg->msgnumber == 0) + if (msg->severity >= 0 || msg->msgnumber == 0) { /* * If the message was something other than informational, and * the severity was greater than 0, then print information to - * stderr with a little pre-amble information. According to + * stderr with a little pre-amble information. According to * the Sybase System Administrator's guide, severity level 10 * messages should not display severity information. */ @@ -1218,8 +1471,10 @@ static CS_RETCODE bcp_server_cb (ctx, con, msg) fprintf( stderr, "\n" ); fprintf( stderr, "%s\n", msg->text ); fflush( stderr ); + + sg_error = True; } - else + else { /* * Otherwise, it is just an informational (e.g. print) message @@ -1261,5 +1516,31 @@ static CS_RETCODE bcp_client_cb ( ctx, con, msg ) fprintf( stderr, "%s\n", msg->msgstring ); fflush( stderr ) ; + sg_error = True; + return CS_SUCCEED ; } + +#if defined(CS_SSLVALIDATE_CB) +/* + * sqsh-2.5 - Validate the servername in a host:port:ssl type of connection + * to be valid for the chosen certificate if the servername does + * not match the CN in the certificate. + */ +static CS_RETCODE validate_srvname_cb (userdata, certptr, certcount, valid) + CS_VOID *userdata; + CS_SSLCERT *certptr; + CS_INT certcount; + CS_INT valid; +{ + if (valid == CS_SSL_INVALID_MISMATCHNAME) + { + return CS_SSL_VALID_CERT; + } + else + { + return valid; + } +} +#endif + diff --git a/src/cmd_buf.c b/src/cmd_buf.c index 9435432..9a29d2f 100644 --- a/src/cmd_buf.c +++ b/src/cmd_buf.c @@ -34,11 +34,12 @@ #include "sqsh_buf.h" #include "sqsh_stdin.h" #include "sqsh_expand.h" /* sqsh-2.1.6 */ +#include "sqsh_init.h" /* sqsh-2.1.6 */ #include "cmd.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_buf.c,v 1.4 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_buf.c,v 1.6 2013/04/18 11:54:43 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -348,8 +349,8 @@ int cmd_buf_load( argc, argv ) * If we don't have any arguments on the command line, or we have too * many arguments, then print usage. */ - if (have_error == True || - (argc - sqsh_optind) < 1 || + if (have_error == True || + (argc - sqsh_optind) < 1 || (argc - sqsh_optind) > 2) { fprintf( stderr, "\\buf-load [-a] filename [dest-buf]\n" ); @@ -409,7 +410,7 @@ int cmd_buf_show( argc, argv ) * structure. Oh well. Anyway, here I just blast through the * hash table, displaying anything I run across. */ - count = 0 ; + count = 0 ; for( i = 0; i < g_buf->env_hsize; i++ ) { for( v = g_buf->env_htable[i]; v != NULL; v = v->var_nxt ) { @@ -418,7 +419,7 @@ int cmd_buf_show( argc, argv ) line = v->var_value ; while( (nl = strchr( line, '\n' )) != NULL ) { - printf( " %*.*s\n", nl - line, nl - line, line ) ; + printf( " %*.*s\n", (int) (nl - line), (int) (nl - line), line ) ; line = nl + 1 ; } @@ -434,9 +435,9 @@ int cmd_buf_show( argc, argv ) * If the user requested that we show a particular buffer and * we couldn't find it, then print an error message. */ - if( buf_name != NULL && count == 0 ) { - fprintf( stderr, "\\buf-show: Buffer %s does not exist\n", buf_name ) ; - return CMD_FAIL ; + if( buf_name != NULL && count == 0 ) { + fprintf( stderr, "\\buf-show: Buffer %s does not exist\n", buf_name ) ; + return CMD_FAIL ; } return CMD_LEAVEBUF ; @@ -459,7 +460,7 @@ int cmd_buf_edit( argc, argv ) extern char *sqsh_optarg ; extern int sqsh_optind ; int c ; - varbuf_t *exp_buf; /* sqsh-2.1.6 feature */ + varbuf_t *exp_buf = NULL; /* sqsh-2.1.6 feature */ /* * The editor can only be run in interactive mode. @@ -515,16 +516,16 @@ int cmd_buf_edit( argc, argv ) * Now, we need to make sure that the buffers that we want to read * from and write to actually exist. */ - if (buf_can_put( write_buf ) == False) + if (buf_can_put( write_buf ) == False) { - fprintf( stderr, "\\buf-edit: %s\n", sqsh_get_errstr() ); - return CMD_FAIL; + fprintf( stderr, "\\buf-edit: %s\n", sqsh_get_errstr() ); + return CMD_FAIL; } /* * Attempt to retrieve the name of the editor from our environment. */ - if (strcmp(argv[0], "edit" ) == 0 || + if (strcmp(argv[0], "edit" ) == 0 || strcmp(argv[0], "\\edit" ) == 0 || strcmp(argv[0], "\\buf-edit" ) == 0) { @@ -560,7 +561,8 @@ int cmd_buf_edit( argc, argv ) * the same program. */ sprintf( path, "%s/sqsh-edit.%d.sql", tmp_dir, (int)getpid() ); - varbuf_destroy( exp_buf ); /* sqsh-2.1.6 feature */ + if (exp_buf != NULL) + varbuf_destroy( exp_buf ); /* sqsh-2.1.6 feature */ /* * Attempt to save the read buffer into the file that we built. @@ -581,7 +583,7 @@ int cmd_buf_edit( argc, argv ) /* * Run the editor. */ - system(str); + c = system(str); if (buf_load( write_buf, path, False ) == False) { diff --git a/src/cmd_connect.c b/src/cmd_connect.c index 0805abf..e1d35cb 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" @@ -33,13 +35,14 @@ #include "sqsh_cmd.h" #include "sqsh_job.h" #include "sqsh_init.h" +#include "sqsh_sig.h" #include "sqsh_stdin.h" #include "cmd.h" #include "sqsh_expand.h" /* sqsh-2.1.6 */ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_connect.c,v 1.22 2010/03/28 11:46:05 mpeppler Exp $"; +static char RCS_Id[] = "$Id: cmd_connect.c,v 1.40 2014/04/04 08:22:38 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -67,45 +70,51 @@ static int sg_login_failed = False; static int timeouts; /*-- Local Prototypes --*/ -static CS_RETCODE syb_server_cb +static CS_RETCODE syb_server_cb _ANSI_ARGS(( CS_CONTEXT*, CS_CONNECTION*, CS_SERVERMSG* )) -#if defined(_CYGWIN32_) +#if defined(__CYGWIN__) __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ +#endif /* __CYGWIN__ */ ; -static CS_RETCODE syb_client_cb +static CS_RETCODE syb_client_cb _ANSI_ARGS(( CS_CONTEXT*, CS_CONNECTION*, CS_CLIENTMSG* )) -#if defined(_CYGWIN32_) +#if defined(__CYGWIN__) __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ +#endif /* __CYGWIN__ */ ; static CS_RETCODE syb_cs_cb _ANSI_ARGS(( CS_CONTEXT*, CS_CLIENTMSG* )) -#if defined(_CYGWIN32_) +#if defined(__CYGWIN__) __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ +#endif /* __CYGWIN__ */ ; +#if defined(CS_SSLVALIDATE_CB) +static CS_RETCODE validate_srvname_cb + _ANSI_ARGS(( CS_VOID*, CS_SSLCERT*, CS_INT, CS_INT )) +#if defined(__CYGWIN__) + __attribute__ ((stdcall)) +#endif /* __CYGWIN__ */ + ; +#endif + static int wrap_print _ANSI_ARGS(( FILE*, char* )) ; static int check_opt_capability _ANSI_ARGS(( CS_CONNECTION * )); /* sqsh-2.1.6 - New function SetNetAuth */ static CS_RETCODE SetNetAuth _ANSI_ARGS(( CS_CONNECTION *, - CS_CHAR *, CS_CHAR *, CS_CHAR *, CS_CHAR *)) -#if defined(_CYGWIN32_) - __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ - ; + CS_CHAR *, CS_CHAR *, CS_CHAR *, CS_CHAR *)); /* sqsh-2.1.7 - New function ShowNetAuthCredExp */ static CS_RETCODE ShowNetAuthCredExp _ANSI_ARGS((CS_CONNECTION *, - CS_CHAR *)) -#if defined(_CYGWIN32_) - __attribute__ ((stdcall)) -#endif /* _CYGWIN32_ */ - ; + CS_CHAR *)); + +/* sqsh-2.2.0 - Signal handler to respond to SIGINT during cmd_connect */ +static JMP_BUF sg_jmp_buf; +static int sg_interrupted; +static void connect_run_sigint ( int, void *); /* * cmd_connect: @@ -143,8 +152,6 @@ int cmd_connect( argc, argv ) char *password ; char *server ; char *interfaces ; - char *colsep ; - char *width ; char *packet_size ; char *autouse ; char *session ; @@ -160,10 +167,11 @@ int cmd_connect( argc, argv ) extern char *sqsh_optarg ; extern int sqsh_optind ; char use_database[128] ; + char *usedbcheck ; int c ; int have_error = False ; int preserve_context = True ; - char orig_password[64]; + char orig_password[SQSH_PASSLEN+1]; int password_changed = False; char sqlbuf[64]; char passbuf[64]; @@ -183,6 +191,12 @@ int cmd_connect( argc, argv ) CS_BOOL NetAuthRequired; varbuf_t *exp_buf = NULL; + /* sqsh-2.2.0 - New variables for TDS debugging with ct_debug() */ +#if defined(DEBUG) && defined(CS_SET_DBG_FILE) && defined(CS_SET_PROTOCOL_FILE) + char *debug_tds_logdata; + char *debug_tds_capture; +#endif + #if defined(CTLIB_SIGPOLL_BUG) && defined(F_SETOWN) int ctlib_fd; #endif @@ -216,164 +230,176 @@ int cmd_connect( argc, argv ) /* * Parse the command line options. * sqsh-2.1.6 - New options added and case evaluation neatly ordered. + * sqsh-2.2.0 - -J option added. -I requires an optarg. */ - while ((c = sqsh_getopt( argc, argv, "cD:I;K:n:N:P;Q:R:S:T:U:V;Z;" )) != EOF) + while ((c = sqsh_getopt( argc, argv, "A:cD:G:I:J:K:n:N:P;Q:R:S:T:U:V;XZ;z:" )) != EOF) { - switch( c ) + switch( c ) { - case 'c' : - preserve_context = False ; - break ; - case 'D' : - if (env_put( g_env, "database", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -D: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break; - case 'I' : - if (env_put( g_env, "interfaces", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -I: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'K' : /* sqsh-2.1.6 */ - if (env_put( g_env, "keytab_file", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -K: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'n' : - if (env_put( g_env, "chained", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -n: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'N' : /* sqsh-2.1.5 */ - if (env_put( g_env, "appname", sqsh_optarg, - ENV_F_TRAN ) == False) { - fprintf( stderr, "\\connect: -N: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break; - case 'P' : - 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) - { - fprintf( stderr, "\\connect: -P: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break; - case 'Q' : /* sqsh-2.1.6 */ - if (env_put( g_env, "query_timeout", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -Q: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'R' : /* sqsh-2.1.6 */ - if (env_put( g_env, "principal", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -R: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'S' : - if (env_put( g_env, "DSQUERY", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -S: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'T' : /* sqsh-2.1.6 */ - if (env_put( g_env, "login_timeout", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -T: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'U' : - if (env_put( g_env, "username", sqsh_optarg, - ENV_F_TRAN ) == False) - { - fprintf( stderr, "\\connect: -U: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'V' : /* sqsh-2.1.6 */ - if (sqsh_optarg == NULL || *sqsh_optarg == '\0') - return_code = env_put( g_env, "secure_options", "u", ENV_F_TRAN); - else - return_code = env_put( g_env, "secure_options", sqsh_optarg, ENV_F_TRAN); - - if (return_code == False) - { - fprintf( stderr, "\\connect: -V: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - case 'Z' : /* sqsh-2.1.6 */ - if (sqsh_optarg == NULL || *sqsh_optarg == '\0') - return_code = env_put( g_env, "secmech", "default", ENV_F_TRAN); - else - return_code = env_put( g_env, "secmech", sqsh_optarg, ENV_F_TRAN); - - if (return_code == False) - { - fprintf( stderr, "\\connect: -Z: %s\n", - sqsh_get_errstr() ); - have_error = True; - } - break ; - - default : - fprintf( stderr, "\\connect: %s\n", sqsh_get_errstr() ) ; - have_error = True ; - break ; + case 'A' : /* sqsh-2.2.0 - Option added */ + if (env_put( g_env, "packet_size", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -A: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'c' : + preserve_context = False ; + break ; + case 'D' : + if (env_put( g_env, "database", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -D: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'G' : /* sqsh-2.2.0 - Option added */ + if (env_put( g_env, "tds_version", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -G: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'I' : + if (env_put( g_env, "interfaces", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -I: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'J' : /* sqsh-2.2.0 - Option added */ + if (env_put( g_env, "charset", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -J: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'K' : /* sqsh-2.1.6 */ + if (env_put( g_env, "keytab_file", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -K: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'n' : + if (env_put( g_env, "chained", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -n: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'N' : /* sqsh-2.1.5 */ + if (env_put( g_env, "appname", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -N: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'P' : + 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) + { + fprintf( stderr, "\\connect: -P: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'Q' : /* sqsh-2.1.6 */ + if (env_put( g_env, "query_timeout", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -Q: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'R' : /* sqsh-2.1.6 */ + if (env_put( g_env, "principal", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -R: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'S' : + if (env_put( g_env, "DSQUERY", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -S: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'T' : /* sqsh-2.1.6 */ + if (env_put( g_env, "login_timeout", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -T: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'U' : + if (env_put( g_env, "username", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -U: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'V' : /* sqsh-2.1.6 */ + if (sqsh_optarg == NULL || *sqsh_optarg == '\0') + return_code = env_put( g_env, "secure_options", "u", ENV_F_TRAN); + else + return_code = env_put( g_env, "secure_options", sqsh_optarg, ENV_F_TRAN); + + if (return_code == False) + { + fprintf( stderr, "\\connect: -V: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'X' : /* sqsh-2.1.9 */ + if (env_put( g_env, "encryption", "1", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -X: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'z' : /* sqsh-2.2.0 - Option added */ + if (env_put( g_env, "language", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\connect: -z: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + case 'Z' : /* sqsh-2.1.6 */ + if (sqsh_optarg == NULL || *sqsh_optarg == '\0') + return_code = env_put( g_env, "secmech", "default", ENV_F_TRAN); + else + return_code = env_put( g_env, "secmech", sqsh_optarg, ENV_F_TRAN); + if (return_code == False) + { + fprintf( stderr, "\\connect: -Z: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break ; + + default : + fprintf( stderr, "\\connect: %s\n", sqsh_get_errstr() ) ; + have_error = True ; + break ; } } /* - * If there are any options left on the end of the line, then - * we have an error. + * If there are any options left on the end of the line, then we have an error. * sqsh-2.1.6 - New options added to the list. + * sqsh-2.2.0 - -J charset added to the list. */ - if( have_error || sqsh_optind != argc ) + if( have_error || sqsh_optind != argc ) { - fprintf( stderr, - "Use: \\connect [-c] [-I interfaces] [-U username] [-P pwd] [-S server]\n" - " [-D database ] [-N appname] [-n {on|off}] [-Q query_timeout]\n" - " [-T login_timeout] [-K keytab_file] [-R principal]\n" - " [-V [bcdimoqru]] [-Z [secmech|default|none]]\n" + fprintf( stderr, + "Use: \\connect [-A packet size] [-c] [-I interfaces] [-U username] [-P pwd] [-S server]\n" + " [-D database ] [-G tds version] [-J charset] [-N appname] [-n {on|off}]\n" + " [-Q query_timeout] [-T login_timeout] [-K keytab_file] [-R principal]\n" + " [-V [bcdimoqru]] [-X] [-z language] [-Z [secmech|default|none]]\n" ) ; - + env_rollback( g_env ); return CMD_FAIL; } @@ -387,8 +413,6 @@ int cmd_connect( argc, argv ) env_get( g_env, "username", &username ) ; env_get( g_env, "DSQUERY", &server ) ; env_get( g_env, "interfaces", &interfaces ) ; - env_get( g_env, "width", &width ) ; - env_get( g_env, "colsep", &colsep ) ; env_get( g_env, "packet_size", &packet_size ) ; env_get( g_env, "autouse", &autouse ) ; env_get( g_env, "database", &database ) ; @@ -419,6 +443,16 @@ 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. + */ + sig_save(); + 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 * is a valid path name, then we want to execute the contents of @@ -430,14 +464,14 @@ int cmd_connect( argc, argv ) if (sqsh_expand( session, exp_buf, 0 ) != False) { session = varbuf_getstr( exp_buf ); - if (session != NULL && access( session, R_OK ) != -1) + if (session != NULL && access( session, R_OK ) != -1) { DBG(sqsh_debug(DEBUG_ENV, "cmd_connect: session file is %s.\n", session);) cp = malloc (strlen(session) + 12) ; sprintf (cp, "\\loop -n %s", session); if ((jobset_run( g_jobset, cp, &exit_status )) == -1 || - exit_status == CMD_FAIL) + exit_status == CMD_FAIL) { fprintf( stderr, "%s\n", sqsh_get_errstr() ); free (cp); @@ -476,7 +510,7 @@ int cmd_connect( argc, argv ) secmech = NULL; secure_options = NULL; } - if ((secmech != NULL && *secmech != '\0') || + if ((secmech != NULL && *secmech != '\0') || (secure_options != NULL && *secure_options != '\0')) { NetAuthRequired = CS_TRUE; @@ -504,7 +538,7 @@ int cmd_connect( argc, argv ) * If we don't have a password to use (i.e. the $password isn't set * or -P was not supplied), then ask the user for one. */ - if (g_password_set == False) + else if (g_password_set == False) { len = sqsh_getinput( "Password: ", passbuf, sizeof(passbuf), 0); @@ -529,9 +563,10 @@ int cmd_connect( argc, argv ) * database, then that indicates that we are to automatically * connect to $database prior to returning. */ - if( preserve_context && database != NULL && *database != '\0' ) + if( preserve_context && database != NULL && *database != '\0' ) { - strncpy( use_database, database , 127) ; + strncpy( use_database, database, sizeof(use_database)-1 ) ; + use_database[sizeof(use_database)-1] = '\0'; autouse = use_database ; } @@ -549,29 +584,47 @@ int cmd_connect( argc, argv ) if (g_context == NULL) { /*-- Allocate a new context structure --*/ - /*-- mpeppler 4/9/2004 + /*-- mpeppler 4/9/2004 we loop through the CS_VERSION_xxx values to try to use the highest one we find */ - retcode = CS_FAIL; + retcode = CS_FAIL; #if defined(CS_CURRENT_VERSION) - if(retcode != CS_SUCCEED) { - g_cs_ver = CS_CURRENT_VERSION; - retcode = cs_ctx_alloc(g_cs_ver, &g_context); -} + if(retcode != CS_SUCCEED) { + g_cs_ver = CS_CURRENT_VERSION; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } +#endif +#if defined(CS_VERSION_160) + if(retcode != CS_SUCCEED) { + g_cs_ver = CS_VERSION_160; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } +#endif +#if defined(CS_VERSION_157) + if(retcode != CS_SUCCEED) { + g_cs_ver = CS_VERSION_157; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } +#endif +#if defined(CS_VERSION_155) + if(retcode != CS_SUCCEED) { + g_cs_ver = CS_VERSION_155; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } #endif #if defined(CS_VERSION_150) if(retcode != CS_SUCCEED) { - g_cs_ver = CS_VERSION_150; - retcode = cs_ctx_alloc(g_cs_ver, &g_context); - } + g_cs_ver = CS_VERSION_150; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } #endif #if defined(CS_VERSION_125) if(retcode != CS_SUCCEED) { - g_cs_ver = CS_VERSION_125; - retcode = cs_ctx_alloc(g_cs_ver, &g_context); - } + g_cs_ver = CS_VERSION_125; + retcode = cs_ctx_alloc(g_cs_ver, &g_context); + } #endif #if defined(CS_VERSION_120) if(retcode != CS_SUCCEED) { @@ -590,6 +643,8 @@ int cmd_connect( argc, argv ) g_cs_ver = CS_VERSION_100; retcode = cs_ctx_alloc(g_cs_ver, &g_context); } + DBG(sqsh_debug(DEBUG_TDS, "cmd_connect: g_cs_ver (CS_VERSION) set to: %d\n", g_cs_ver);) + if (retcode != CS_SUCCEED) /* nothing worked... */ goto connect_fail; @@ -600,32 +655,32 @@ int cmd_connect( argc, argv ) (CS_VOID*)syb_cs_cb, /* Buffer */ CS_UNUSED, /* Buffer length */ (CS_INT*)NULL /* Output length */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { fprintf( stderr, "\\connect: Unable to install message callback\n" ); goto connect_fail; } - + /*-- Initialize the context --*/ if (ct_init( g_context, g_cs_ver ) != CS_SUCCEED) 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; - + /* * Set the I/O type to syncronous (things would really freak out * in an async environment). @@ -633,12 +688,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 @@ -658,7 +713,7 @@ int cmd_connect( argc, argv ) { DBG(sqsh_debug(DEBUG_ERROR, "ct_config: Failed to set CS_TIMEOUT to %d seconds.\n", SybTimeOut);) goto connect_fail; - } + } DBG(sqsh_debug(DEBUG_ERROR, "ct_config: CS_TIMEOUT set to %d seconds.\n", SybTimeOut);) } @@ -672,7 +727,7 @@ int cmd_connect( argc, argv ) CS_UNUSED, /* Buffer Length */ NULL /* Output Length */ ) != CS_SUCCEED) - { + { DBG(sqsh_debug(DEBUG_ERROR, "ct_config: Failed to set CS_LOGIN_TIMEOUT to %d seconds.\n", SybTimeOut);) goto connect_fail; } @@ -699,7 +754,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 @@ -747,7 +802,7 @@ int cmd_connect( argc, argv ) { fprintf( stderr, "sqsh: Error expanding $keytab_file: %s\n", sqsh_get_errstr() ); - cp = NULL; + cp = NULL; } } else @@ -788,7 +843,7 @@ int cmd_connect( argc, argv ) ) != CS_SUCCEED) goto connect_fail; } - + if (tds_version != NULL && *tds_version != '\0') /* sqsh-2.1.6 fix on *tds_version */ { if (strcmp(tds_version, "4.0") == 0) @@ -802,7 +857,7 @@ int cmd_connect( argc, argv ) else if (strcmp(tds_version, "5.0") == 0) version = CS_TDS_50; #if !defined(CS_TDS_50) - /* Then we use freetds */ + /* Then we use freetds which uses enum instead of defines */ else if (strcmp(tds_version, "7.0") == 0) version = CS_TDS_70; else if (strcmp(tds_version, "8.0") == 0) @@ -811,21 +866,21 @@ int cmd_connect( argc, argv ) else version = CS_TDS_50; /* default version */ - if (ct_con_props(g_connection, CS_SET, CS_TDS_VERSION, + if (ct_con_props(g_connection, CS_SET, CS_TDS_VERSION, (CS_VOID*)&version, CS_UNUSED, (CS_INT*)NULL) != CS_SUCCEED) goto connect_fail; } /*-- Hostname --*/ - if (hostname != NULL && *hostname != '\0') + 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; } @@ -834,27 +889,44 @@ 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; } /*-- Encryption --*/ - if (encryption != NULL && *encryption == '1') + if (encryption != NULL && *encryption == '1') { 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) + /* + * sqsh-2.1.9: Enable extended password encryption to be able to + * 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) + goto connect_fail; +#endif + } /* @@ -868,69 +940,187 @@ 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( 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 */ -#if defined(CS_SERVERADDR) - if(server && (cp = strchr(server, ':'))) { - if(*cp) - *cp = ' '; - - /* fprintf(stderr, "Using %s for CS_SERVERADDR\n", server);*/ - - if (ct_con_props( g_connection, CS_SET, CS_SERVERADDR, - (CS_VOID*)server, - CS_NULLTERM, (CS_INT*)NULL) != CS_SUCCEED) - goto connect_fail; + /* + * sqsh-2.5 - Work around a bug in FreeTDS and do not call ct_con_props + * for server:port connections but let ct_connect handle it. + * OpenClient supports an optional filter that can be specified as third + * parameter like host:port:filter. Filters are defined in libtcl.cfg. + */ +#if defined(CS_SERVERADDR) && defined(CS_TDS_50) + if ( server != NULL && (cp = strchr(server, ':')) != NULL ) + { + char *cp2; + + *cp = ' '; + if ( (cp2 = strchr(cp+1, ':')) != NULL) /* Optional filter specified? */ + *cp2 = ' '; + + if (ct_con_props( g_connection, + CS_SET, + CS_SERVERADDR, + (CS_VOID*)server, + CS_NULLTERM, + (CS_INT*)NULL + ) != CS_SUCCEED) + goto connect_fail; + + if (cp2 != NULL) + *cp2 = '\0'; /* Remove optional filter from the servername */ + *cp = ':'; /* Put a ':' back into the display servername */ + +#if defined(CS_SSLVALIDATE_CB) + if (ct_callback( g_context, /* Context */ + (CS_CONNECTION*)NULL, /* Connection */ + CS_SET, /* Action */ + CS_SSLVALIDATE_CB, /* Type */ + (CS_VOID*)validate_srvname_cb /* Callback Pointer */ + ) != CS_SUCCEED) + goto connect_fail; +#endif + } +#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 */ + CS_NULLTERM /* String '\0' terminated */ + ) != 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 */ + CS_NULLTERM /* String '\0' terminated */ + ) != 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 + * We sit in a loop and attempt to connect while we are getting * "Login failed" messages. */ do @@ -947,10 +1137,15 @@ int cmd_connect( argc, argv ) * error handlers. */ if (ct_connect( g_connection, server, - (server == NULL)?CS_UNUSED:CS_NULLTERM ) != CS_SUCCEED) + (server == NULL) ? CS_UNUSED : CS_NULLTERM ) != CS_SUCCEED) { - if (*password_retry != '1' || !sqsh_stdin_isatty() || - sg_login_failed != True) + /* + * sqsh-2.1.9: Check for g_interactive instead of sqsh_stdin_isatty() + * because that may not be determined at this point. Do not prompt + * for a password if Network authentication is used but just failed. + */ + if (*password_retry != '1' || g_interactive == False || + sg_login_failed != True || NetAuthRequired == True) { goto connect_fail; } @@ -980,6 +1175,7 @@ int cmd_connect( argc, argv ) } } while (sg_login_failed == True); + sg_login = False; /* XXX */ /* ct_cancel(g_connection, NULL, CS_CANCEL_ALL); */ @@ -994,12 +1190,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" ); @@ -1010,18 +1206,18 @@ int cmd_connect( argc, argv ) * Here is the cruxt of the situation. Async I/O works by delivering * the signal SIGPOLL or SIGIO every time a socket is ready to do * some work (either send or receive data). Normally, this signal - * will only be delivered to the process that requested the + * will only be delivered to the process that requested the * facility. Unfortunately, on some platforms, CT-Lib is explicitly * requesting that the signal be sent to every process in the same * process group! This means that when sqsh spawns a child process * during a pipe (e.g. "go | more") the child process will receive - * the SIGPOLL signal as well as sqsh...and, since 99% of the + * the SIGPOLL signal as well as sqsh...and, since 99% of the * programs out there don't know how to deal with SIGPOLL, they * will simply exit. Not a good situation. */ if (fcntl( ctlib_fd, F_SETOWN, getpid() ) == -1) { - fprintf( stderr, + fprintf( stderr, "\\connect: WARNING: Cannot work around CT-Lib SIGPOLL bug: %s\n", strerror(errno) ); } @@ -1039,37 +1235,37 @@ int cmd_connect( argc, argv ) CS_TDS_VERSION, /* Property */ (CS_VOID*)&version, /* Buffer */ CS_UNUSED, /* Buffer Length */ - (CS_INT*)NULL ) == CS_SUCCEED) - { - switch (version) { - case CS_TDS_40: - env_set( g_env, "tds_version", "4.0" ); - break; - case CS_TDS_42: - env_set( g_env, "tds_version", "4.2" ); - break; - case CS_TDS_46: - env_set( g_env, "tds_version", "4.6" ); - break; - case CS_TDS_495: - env_set( g_env, "tds_version", "4.9.5" ); - break; - case CS_TDS_50: - env_set( g_env, "tds_version", "5.0" ); - break; + (CS_INT*)NULL + ) == CS_SUCCEED) + { + switch (version) { + case CS_TDS_40: + env_set( g_env, "tds_version", "4.0" ); + break; + case CS_TDS_42: + env_set( g_env, "tds_version", "4.2" ); + break; + case CS_TDS_46: + env_set( g_env, "tds_version", "4.6" ); + break; + case CS_TDS_495: + env_set( g_env, "tds_version", "4.9.5" ); + break; + case CS_TDS_50: + env_set( g_env, "tds_version", "5.0" ); + break; #if !defined(CS_TDS_50) - case CS_TDS_70: - env_set( g_env, "tds_version", "7.0" ); - break; - case CS_TDS_80: - env_set( g_env, "tds_version", "8.0" ); - break; + case CS_TDS_70: + env_set( g_env, "tds_version", "7.0" ); + break; + case CS_TDS_80: + env_set( g_env, "tds_version", "8.0" ); + break; #endif - default: - env_set( g_env, "tds_version", "unknown" ); - } - } - + default: + env_set( g_env, "tds_version", "unknown" ); + } + } } /* @@ -1082,10 +1278,8 @@ int cmd_connect( argc, argv ) } /*-- If autouse has been set, use it --*/ - if (autouse != NULL && *autouse != '\0') + if (autouse != NULL && *autouse != '\0') { - CS_INT ret = CS_SUCCEED; - if (ct_cmd_alloc( g_connection, &cmd ) != CS_SUCCEED) goto connect_succeed; @@ -1096,24 +1290,33 @@ int cmd_connect( argc, argv ) sqlbuf, /* Buffer */ CS_NULLTERM, /* Buffer Length */ CS_UNUSED /* Options */ - ) != CS_SUCCEED) + ) != CS_SUCCEED) { ct_cmd_drop( cmd ); - goto connect_succeed; + goto connect_fail; } - if (ct_send( cmd ) != CS_SUCCEED) + if (ct_send( cmd ) != CS_SUCCEED) { ct_cmd_drop( cmd ); - goto connect_succeed; + goto connect_fail; } - while (ct_results( cmd, &result_type ) != CS_END_RESULTS) { - if(result_type == CS_CMD_FAIL) - ret = CS_FAIL; - } + while (ct_results( cmd, &result_type ) != CS_END_RESULTS); ct_cmd_drop( cmd ); + /* + * sqsh-2.4 - Check in batch mode if the -D <database> is correctly set. + * Otherwise, abort to prevent script execution in wrong default + * database. + */ + env_get ( g_env, "database", &database ) ; /* Need to refresh var pointer */ + env_get ( g_env, "usedbcheck", &usedbcheck ) ; + if (g_interactive != True && *usedbcheck == '1' && strcmp (autouse, database) != 0) + { + fprintf (stderr, "sqsh: ERROR: Unable to use database '%s' in batch mode\n", autouse); + sqsh_exit(254); + } } connect_succeed: @@ -1131,14 +1334,14 @@ connect_succeed: /* Set chained mode, if necessary. */ if ( chained != NULL && *chained != '\0') /* sqsh-2.1.6 sanity check */ { - if ( check_opt_capability( g_connection ) ) + if ( check_opt_capability( g_connection ) ) { CS_BOOL value = (*chained == '1' ? CS_TRUE : CS_FALSE); retcode = ct_options( g_connection, CS_SET, CS_OPT_CHAINXACTS, &value, CS_UNUSED, NULL); if (retcode != CS_SUCCEED) { - fprintf (stderr, + fprintf (stderr, "\\connect: WARNING: Unable to set transaction mode %s\n", (*chained == '1' ? "on" : "off")); } @@ -1165,16 +1368,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; @@ -1184,7 +1387,8 @@ connect_fail: if (con_status == CS_CONSTAT_CONNECTED) { DBG(sqsh_debug(DEBUG_ERROR, "connect: Closing connection\n");) - ct_close( g_connection, CS_FORCE_CLOSE ); + if (ct_close( g_connection, CS_UNUSED ) != CS_SUCCEED) + ct_close( g_connection, CS_FORCE_CLOSE ); } else { @@ -1196,19 +1400,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");) - 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; @@ -1218,7 +1425,7 @@ connect_leave: if ( exp_buf != NULL) varbuf_destroy( exp_buf ); - sg_login = False; + sig_restore(); return return_code; } @@ -1247,12 +1454,16 @@ int cmd_snace( argc, argv ) static int check_opt_capability( g_connection ) CS_CONNECTION *g_connection; { - CS_BOOL val; - CS_RETCODE ret = ct_capability(g_connection, CS_GET, - CS_CAP_REQUEST, - CS_OPTION_GET, (CS_VOID*)&val); - if(ret != CS_SUCCEED || val == CS_FALSE) - return 0; + CS_BOOL val; + CS_RETCODE ret; + + ret = ct_capability( g_connection, + CS_GET, + CS_CAP_REQUEST, + CS_OPTION_GET, (CS_VOID*)&val + ); + if (ret != CS_SUCCEED || val == CS_FALSE) + return 0; return 1; } @@ -1277,11 +1488,11 @@ static int wrap_print( outfile, str ) cur_end = str + min(len, width) ; end = str + len ; - while( len > 0 && cur_end <= end ) + while( len > 0 && cur_end <= end ) { /*-- Move backwards until we hit whitespace --*/ - if( cur_end < end ) + if( cur_end < end ) { while( cur_end != start && !(isspace((int)*cur_end)) ) --cur_end ; @@ -1290,10 +1501,10 @@ static int wrap_print( outfile, str ) if( cur_end == start ) cur_end = start + (min(len, width)) ; } - + /*-- Print out the line --*/ fprintf( outfile, "%*.*s", (int)(cur_end - start), - (int)(cur_end - start), + (int)(cur_end - start), start ) ; if (*(cur_end-1) != '\n') @@ -1331,13 +1542,19 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) char var_value[31]; int i; char *c; + /* sqsh-2.5 - New variables to support feature p2f */ + char *p2faxm; + int p2faxm_int; + char *p2fname; + FILE *dest_fp; + int p2fstat = False; /* * Record last error in $? */ if (msg->severity > 10) { - sprintf( var_value, "%d", msg->msgnumber ); + sprintf( var_value, "%d", (int) msg->msgnumber ); env_set( g_internal_env, "?", var_value ); } @@ -1348,11 +1565,11 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) * appropriate variable. */ if( msg->msgnumber == 5701 || /* database context change */ - msg->msgnumber == 5703 || /* language changed */ - msg->msgnumber == 5704 ) /* charset changed */ + msg->msgnumber == 5703 || /* language changed */ + msg->msgnumber == 5704 ) /* charset changed */ { - if (msg->text != NULL && (c = strchr( msg->text, '\'' )) != NULL) + if (msg->text != NULL && (c = strchr( msg->text, '\'' )) != NULL) { i = 0; for( ++c; i <= 30 && *c != '\0' && *c != '\''; ++c ) @@ -1366,10 +1583,14 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) */ if (strcmp( var_value, "<NULL>" ) != 0) { - switch (msg->msgnumber) + switch (msg->msgnumber) { - case 5701 : + case 5701 : env_set( g_env, "database", var_value ); +#if defined(USE_READLINE) + /* sqsh-2.1.8 - Feature dynamic keyword load */ + env_set( g_internal_env, "keyword_refresh", "1" ); +#endif break; case 5703 : env_set( g_env, "language", var_value ); @@ -1386,9 +1607,14 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) } /* - * If we got a login failed message, then record it as such as return. + * If we got a login failed message, then record it as such and return. + * sqsh-2.1.8 : Fix password_retry for Sybase RepServer and Microsoft MSSQL connections. + * We also need to check for sg_login == True, i.e. we are in the middle of a login attempt. */ - if (msg->msgnumber == 4002) + if (sg_login == True && (msg->msgnumber == 1017 || /* DCO/ECDA Oracle */ + msg->msgnumber == 4002 || /* Sybase ASE/ASA/IQ */ + msg->msgnumber == 14021 || /* Sybase RepServer */ + msg->msgnumber == 18456)) /* Microsoft MSSQL */ { wrap_print( stderr, msg->text ); sg_login_failed = True; @@ -1397,7 +1623,7 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) /* * Retrieve the threshold severity level for ignoring errors. - * If the variable is set and severity is less than the + * If the variable is set and severity is less than the * threshold, then return without printing out the message. */ env_get( g_env, "thresh_display", &thresh_display ); @@ -1409,37 +1635,63 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) * If the severity is something other than 0 or the msg number is * 0 (user informational messages). */ - if (msg->severity >= 0 || msg->msgnumber == 10) + if (msg->severity >= 0 || msg->msgnumber == 10) { /* + * sqsh-2.5 : Implementation of p2f feature. + * When the number of messages handled by this callback handler exceeds the limit specified in p2faxm, + * and a file is provided in $p2fname and is succesfully opened and we are in interactive mode, then + * write the remaining messages from the current batch to this file instead of on screen. + * Note that global variable g_p2fc will be reset to zero for each new batch in dsp.c. + */ + env_get( g_env, "p2faxm", &p2faxm ); + p2faxm_int = (p2faxm != NULL) ? atoi(p2faxm) : 0; + if (++g_p2fc > p2faxm_int && + p2faxm_int > 0 && + g_p2f_fp != NULL && + g_interactive == True) + { + if (g_p2fc == p2faxm_int + 1) { + env_get( g_env, "p2fname", &p2fname ); + fprintf (stderr,"Warning: Number of printed server messages exceeds p2faxm=%d limit for current batch.\n", p2faxm_int); + fprintf (stderr," Remaining server messages will be printed to file: %s\n", p2fname); + fflush (stderr ); + fprintf (g_p2f_fp, "--------\n"); + } + p2fstat = True; + } + + /* * If the message was something other than informational, and * the severity was greater than 0, then print information to - * stderr with a little pre-amble information. According to + * stderr with a little pre-amble information. According to * the Sybase System Administrator's guide, severity level 10 * messages should not display severity information. */ if (msg->msgnumber > 0 && msg->severity > 10) { - fprintf( stderr, "Msg %d, Level %d, State %d\n", + dest_fp = (p2fstat == True) ? g_p2f_fp : stderr; + fprintf( dest_fp, "Msg %d, Level %d, State %d\n", (int)msg->msgnumber, (int)msg->severity, (int)msg->state ); if (msg->svrnlen > 0) - fprintf( stderr, "Server '%s'", (char*)msg->svrname ); + fprintf( dest_fp, "Server '%s'", (char*)msg->svrname ); if (msg->proclen > 0) - fprintf( stderr, ", Procedure '%s'", (char*)msg->proc ); + fprintf( dest_fp, ", Procedure '%s'", (char*)msg->proc ); if( msg->line > 0 ) - fprintf( stderr, ", Line %d", (int)msg->line ); - fprintf( stderr, "\n" ); - wrap_print( stderr, msg->text ); - fflush( stderr ); + fprintf( dest_fp, ", Line %d", (int)msg->line ); + fprintf( dest_fp, "\n" ); + wrap_print( dest_fp, msg->text ); + fflush( dest_fp ); } - else + else { /* * Otherwise, it is just an informational (e.g. print) message * from the server, so send it to stdout. */ - wrap_print( stdout, msg->text ); - fflush( stdout ); + dest_fp = (p2fstat == True) ? g_p2f_fp : stdout; + wrap_print( dest_fp, msg->text ); + fflush( dest_fp ); } } } @@ -1450,7 +1702,7 @@ static CS_RETCODE syb_server_cb (ctx, con, msg) */ env_get( g_env, "thresh_fail", &thresh_fail ); - if (thresh_fail != NULL && msg->severity >= (CS_INT)atoi(thresh_fail)) + if (thresh_fail != NULL && msg->severity >= (CS_INT)atoi(thresh_fail)) { DBG(sqsh_debug(DEBUG_ERROR, "syb_server_cb: thresh_fail = %s, severity = %d, incrementing batch_failcount\n", @@ -1476,13 +1728,17 @@ static CS_RETCODE syb_cs_cb ( ctx, msg ) /* * If this is the "The attempt to connect to the server failed" * message and we previously got a "Login Failed" message from - * the server, then ignore it. + * the server (44), then ignore it. + * + * sqsh-2.1.9: The same for the freetds "Adaptive Server connection failed" + * message number 34. Also check for g_interactive and display the Client + * Message if the session is not interactive. */ - if (CS_NUMBER(msg->msgnumber) == 44 && sg_login_failed == True) + if ((CS_NUMBER(msg->msgnumber) == 34 || CS_NUMBER(msg->msgnumber) == 44) + && sg_login_failed == True && g_interactive == True) { return CS_SUCCEED; } - fprintf( stderr, "Open Client Message\n" ); if (CS_NUMBER(msg->msgnumber) > 0) @@ -1543,10 +1799,17 @@ static CS_RETCODE syb_client_cb ( ctx, con, msg ) if (sg_login == False) { env_get( g_env, "DSQUERY", &server ) ; - if (CS_SEVERITY(msg->msgnumber) >= CS_SV_COMM_FAIL || ctx == NULL || - con == NULL) +#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, CS_SEVERITY(msg->msgnumber) ); + fprintf (stderr, "%s: Aborting on severity %d\n", server, (int) CS_SEVERITY(msg->msgnumber) ); sqsh_exit(254); } } @@ -1560,14 +1823,15 @@ static CS_RETCODE syb_client_cb ( ctx, con, msg ) env_get( g_env, "DSQUERY", &server ) ; env_get( g_env, "max_timeout", &max_timeout ) ; if (max_timeout != NULL && *max_timeout != '\0' && atoi(max_timeout) > 0) - if (timeouts >= atoi(max_timeout)) - { - fprintf (stderr, "%s: Query or command timeout detected, session aborted\n", server); - fprintf (stderr, "%s: The client connection has detected this %d time(s).\n", server, timeouts); - fprintf (stderr, "%s: Aborting on max_timeout limit %s\n", server, max_timeout ); - sqsh_exit(254); - } - + { + if (timeouts >= atoi(max_timeout)) + { + fprintf (stderr, "%s: Query or command timeout detected, session aborted\n", server); + fprintf (stderr, "%s: The client connection has detected this %d time(s).\n", server, timeouts); + fprintf (stderr, "%s: Aborting on max_timeout limit %s\n", server, max_timeout ); + sqsh_exit(254); + } + } if (ct_con_props (con, CS_GET, CS_LOGIN_STATUS, (CS_VOID *)&status, CS_UNUSED, NULL) != CS_SUCCEED) { fprintf (stderr,"%s: ct_con_props() failed\n", server); @@ -1603,8 +1867,7 @@ static CS_RETCODE syb_client_cb ( ctx, con, msg ) * * Return : CS_FAIL or CS_SUCCEED */ -static CS_RETCODE -SetNetAuth (conn, principal, keytab_file, secmech, req_options) +static CS_RETCODE SetNetAuth (conn, principal, keytab_file, secmech, req_options) CS_CONNECTION *conn; CS_CHAR *principal; CS_CHAR *keytab_file; @@ -1620,7 +1883,7 @@ SetNetAuth (conn, principal, keytab_file, secmech, req_options) CS_BOOL OptSupported; NET_SEC_SERVICE nss[] = { - /* + /* * CS_SEC_NETWORKAUTH must be the first entry */ { CS_SEC_NETWORKAUTH, 'u', "Network user authentication (unified login)" }, @@ -1778,13 +2041,13 @@ SetNetAuth (conn, principal, keytab_file, secmech, req_options) #endif } + /* * Function: ShowNetAuthCredExp() * * Show the credential expiration timeout period of a network authenticated session. */ -static CS_RETCODE -ShowNetAuthCredExp (conn, cmdname) +static CS_RETCODE ShowNetAuthCredExp (conn, cmdname) CS_CONNECTION *conn; CS_CHAR *cmdname; { @@ -1794,6 +2057,8 @@ ShowNetAuthCredExp (conn, cmdname) char *datetime; char dttm[32]; time_t exp_time; + char *fmt; + char *cp; /* * Check if current session is Network Authenticated. @@ -1827,8 +2092,8 @@ ShowNetAuthCredExp (conn, cmdname) return CS_FAIL; } - switch (CredTimeOut) - { + switch (CredTimeOut) + { case CS_NO_LIMIT: fprintf (stdout, "%s: Network Authenticated session does not expire\n", cmdname); break; @@ -1842,13 +2107,30 @@ ShowNetAuthCredExp (conn, cmdname) break; default: - env_get( g_env, "datetime", &datetime ) ; - if (datetime == NULL || datetime[0] == '\0' || strcmp(datetime,"default") == 0) - datetime = "%Y%m%d %H:%M:%S"; exp_time = time (NULL) + CredTimeOut; - cftime( dttm, datetime, &exp_time ) ; + env_get( g_env, "datetime", &datetime ) ; + if (datetime == NULL || datetime[0] == '\0' || strcmp(datetime, "default") == 0) + { + cftime( dttm, "%Y%m%d %H:%M:%S", &exp_time ); + } + else + { + fmt = (char *) malloc (sizeof(char) * strlen(datetime)+2); + for (cp = fmt; *datetime != '\0'; datetime++) + { + if (*datetime == '.' && *(datetime+1) == '%' && *(datetime+2) == 'q') + { + datetime += 2; + } + else if (*datetime != '[' && *datetime != ']') + *cp++ = *datetime; + } + *cp = '\0'; + cftime( dttm, fmt, &exp_time ); + free (fmt); + } fprintf (stdout, "%s: Network Authenticated session expires at: %s (%d secs)\n", - cmdname, dttm, CredTimeOut ); + cmdname, dttm, (int) CredTimeOut ); } } else @@ -1860,3 +2142,42 @@ ShowNetAuthCredExp (conn, cmdname) #endif } + +/* + * connect_run_sigint(): + * + * This function is called whenever a SIGINT signal is received while processing cmd_connect. + * Its only real job is to return to the point where the SETJMP function was executed. + */ +static void connect_run_sigint (sig, user_data ) + int sig; + void *user_data; +{ + sg_interrupted = True; + LONGJMP (sg_jmp_buf, 1); +} + + +#if defined(CS_SSLVALIDATE_CB) +/* + * sqsh-2.5 - Validate the servername in a host:port:ssl type of connection + * to be valid for the chosen certificate if the servername does + * not match the CN in the certificate. + */ +static CS_RETCODE validate_srvname_cb (userdata, certptr, certcount, valid) + CS_VOID *userdata; + CS_SSLCERT *certptr; + CS_INT certcount; + CS_INT valid; +{ + if (valid == CS_SSL_INVALID_MISMATCHNAME) + { + return CS_SSL_VALID_CERT; + } + else + { + return valid; + } +} +#endif + diff --git a/src/cmd_do.c b/src/cmd_do.c index 0956314..e44dc18 100644 --- a/src/cmd_do.c +++ b/src/cmd_do.c @@ -51,8 +51,8 @@ static int cmd_do_exec _ANSI_ARGS(( CS_CONNECTION*, char*, char* )); /* -** 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. */ @@ -74,7 +74,9 @@ int cmd_do( argc, argv ) varbuf_t *do_buf; varbuf_t *orig_sqlbuf; /* SQL Buffer upon entry */ CS_CONNECTION *orig_conn; /* Connection upon entry */ - int ret; + CS_CONTEXT *orig_ctxt; /* Context upon entry */ + char orig_password[SQSH_PASSLEN+1] = ""; /* Current session password */ + int ret = False; int have_error = False; int exit_status; int do_connection = True; @@ -86,9 +88,23 @@ int cmd_do( argc, argv ) */ env_tran( g_env ); - while ((ch = sqsh_getopt( argc, argv, "S:U:P:D:n" )) != EOF) + /* + * sqsh-2.4 modification. + * This is totally utterly ugly, but the \do block may call \reconnect with a lot of + * parameter changes that will be committed in the global environment upon a successfull + * connection. If we put some of the original values on the logsave chain first, then the + * env_rollback call at the end of this function will eventually restore these parameter + * values back to the values of the current session. + */ + env_get( g_env, "DSQUERY", &expand); env_put( g_env, "DSQUERY", expand, ENV_F_TRAN ); + env_get( g_env, "database", &expand); env_put( g_env, "database", expand, ENV_F_TRAN ); + env_get( g_env, "username", &expand); env_put( g_env, "username", expand, ENV_F_TRAN ); + if (g_password != NULL) + strcpy ( orig_password, g_password); + + while ((ch = sqsh_getopt( argc, argv, "S:U:P:D:n" )) != EOF) { - switch (ch) + switch (ch) { case 'n' : do_connection = False; @@ -107,14 +123,12 @@ int cmd_do( argc, argv ) ret = env_put( g_env, "database", sqsh_optarg, ENV_F_TRAN ); break; default : - fprintf( stderr, "\\do: -%c: Invalid option\n", - (int)ch ); - have_error = True; + ret = False; } if (ret != True) { - fprintf( stderr, "\\do: -%c: %s\n", ch, sqsh_get_errstr() ); + fprintf( stderr, "\\do: %s\n", sqsh_get_errstr() ); have_error = True; } } @@ -123,9 +137,9 @@ int cmd_do( argc, argv ) ** If there are any errors on the command line, or there are ** any options left over then we have an error. */ - if( (argc - sqsh_optind) > 0 || have_error == True) + if( (argc - sqsh_optind) > 0 || have_error == True) { - fprintf( stderr, + fprintf( stderr, "Use: \\do [-n] [-S server] [-U user] [-P pass] [-D db]\n" " -n Do not establish new connection (cannot issue SQL)\n" " -S Perform do-loop on specified server\n" @@ -168,7 +182,7 @@ int cmd_do( argc, argv ) } /* - ** Before we go any further, read the reaminder of the input + ** Before we go any further, read the remainder of the input ** from the user (up to \done). */ do_buf = varbuf_create( 512 ); @@ -196,7 +210,7 @@ int cmd_do( argc, argv ) return(CMD_FAIL); } - if (sqsh_expand( varbuf_getstr( g_sqlbuf ), expand_buf, + if (sqsh_expand( varbuf_getstr( g_sqlbuf ), expand_buf, (EXP_STRIPESC|EXP_COMMENT|EXP_COLUMNS) ) == False) { fprintf( stderr, "\\do: Expansion failure: %s\n", @@ -223,9 +237,10 @@ int cmd_do( argc, argv ) */ orig_sqlbuf = g_sqlbuf; orig_conn = g_connection; + orig_ctxt = g_context; /* - ** And replace then with new copies. Note that setting + ** And replace then with new copies. Note that setting ** g_connection to NULL will cause a new connection to be ** established for us by \connect. */ @@ -242,7 +257,8 @@ int cmd_do( argc, argv ) if (do_connection == True) { g_connection = NULL; - if (jobset_run( g_jobset, "\\connect", &exit_status ) == -1) + g_context = NULL; + if (jobset_run( g_jobset, "\\connect", &exit_status ) == -1) { fprintf( stderr, "\\do: Connect failed\n" ); ret = exit_status; @@ -254,17 +270,28 @@ int cmd_do( argc, argv ) ret = cmd_do_exec( orig_conn, sql, varbuf_getstr(do_buf) ); } - if (do_connection == True && + if (do_connection == True && g_connection != NULL) { - ct_close( g_connection, CS_FORCE_CLOSE ); + if (ct_close( g_connection, CS_UNUSED ) != CS_SUCCEED) + ct_close( g_connection, CS_FORCE_CLOSE ); ct_con_drop( g_connection ); g_connection = NULL; } + if (do_connection == True && + g_context != NULL) + { + if (ct_exit ( g_context, CS_UNUSED) != CS_SUCCEED) + ct_exit ( g_context, CS_FORCE_EXIT ); + cs_ctx_drop ( g_context ); + g_context = NULL; + } + varbuf_destroy( g_sqlbuf ); varbuf_destroy( do_buf ); + g_context = orig_ctxt; g_connection = orig_conn; g_sqlbuf = orig_sqlbuf; @@ -272,6 +299,7 @@ int cmd_do( argc, argv ) varbuf_destroy( expand_buf ); env_rollback( g_env ); + env_set( g_env, "password", orig_password ); return(ret); } @@ -289,6 +317,9 @@ static int cmd_do_exec( conn, sql, dobuf ) /* ** Save away current signal context. + ** + ** sqsh-2.5: Make sure that the signal context is restored using sig_restore() prior + ** to every return from this function. */ sig_save(); @@ -314,24 +345,27 @@ static int cmd_do_exec( conn, sql, dobuf ) { fprintf( stderr, "\\do: Error initializing command\n" ); - sig_restore(); ct_cmd_drop( cmd ); + sig_restore(); return(CMD_FAIL); } + /* sqsh-2.5 - Feature p2f, reset g_p2fc before a new batch is started */ + g_p2fc = 0; + if (ct_send( cmd ) != CS_SUCCEED) { fprintf( stderr, "\\do: Error sending command\n" ); - sig_restore(); ct_cmd_drop( cmd ); + sig_restore(); return(CMD_FAIL); } /* ** Suck in the results. */ - while ((retcode = ct_results( cmd, &result_type )) + while ((retcode = ct_results( cmd, &result_type )) == CS_SUCCEED) { /* @@ -341,6 +375,7 @@ static int cmd_do_exec( conn, sql, dobuf ) { ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); + sig_restore(); return(CMD_INTERRUPTED); } @@ -355,6 +390,7 @@ static int cmd_do_exec( conn, sql, dobuf ) { ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); + sig_restore(); if (retcode == CS_CANCELED) { @@ -373,6 +409,7 @@ static int cmd_do_exec( conn, sql, dobuf ) { ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); + sig_restore(); return(CMD_FAIL); } @@ -381,12 +418,13 @@ static int cmd_do_exec( conn, sql, dobuf ) ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); dsp_desc_destroy( desc ); + sig_restore(); return(CMD_INTERRUPTED); } /* ** Save away the column description in the global table - ** of column descriptions (these will be referenced + ** of column descriptions (these will be referenced ** during expansion of the sqlbuf. */ g_do_cols[g_do_ncols] = desc; @@ -401,8 +439,8 @@ static int cmd_do_exec( conn, sql, dobuf ) ** For each row we fetch back, we want to execute ** the dobuf. */ - if ((ret = cmd_input()) == CMD_FAIL || - ret == CMD_ABORT || + if ((ret = cmd_input()) == CMD_FAIL || + ret == CMD_ABORT || ret == CMD_INTERRUPTED || ret == CMD_BREAK || ret == CMD_RETURN) @@ -417,6 +455,7 @@ static int cmd_do_exec( conn, sql, dobuf ) */ if (ret == CMD_BREAK) { + sig_restore(); return(CMD_LEAVEBUF); } @@ -424,6 +463,7 @@ static int cmd_do_exec( conn, sql, dobuf ) ct_cmd_drop( cmd ); dsp_desc_destroy( desc ); --g_do_ncols; + sig_restore(); return(ret); } @@ -434,6 +474,7 @@ static int cmd_do_exec( conn, sql, dobuf ) ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); dsp_desc_destroy( desc ); + sig_restore(); return(CMD_INTERRUPTED); } } @@ -445,6 +486,7 @@ static int cmd_do_exec( conn, sql, dobuf ) { ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); + sig_restore(); if (retcode == CS_CANCELED) { @@ -463,10 +505,12 @@ static int cmd_do_exec( conn, sql, dobuf ) { ct_cancel( conn, (CS_COMMAND*)NULL, CS_CANCEL_ALL ); ct_cmd_drop( cmd ); + sig_restore(); return(CMD_FAIL); } ct_cmd_drop( cmd ); + sig_restore(); return(CMD_RESETBUF); } @@ -603,7 +647,7 @@ int cmd_body_input( buf ) if (*cp == '\\') { ++cp; - for(i = 0; i < (sizeof(cmd)-1) && *cp != '\0' && + for(i = 0; i < (sizeof(cmd)-1) && *cp != '\0' && isalpha((int)*cp); ++i, ++cp) { cmd[i] = *cp; @@ -629,9 +673,10 @@ int cmd_body_input( buf ) prompt_indent[i] = '\0'; env_put( g_env, "prompt_indent", prompt_indent, ENV_F_TRAN ); } - else if ((strcmp( cmd, "do" ) == 0) || - strcmp( cmd, "func" ) == 0 || - strcmp( cmd, "while" ) == 0) + else if ( strcmp( cmd, "do" ) == 0 || + strcmp( cmd, "for" ) == 0 || /* sqsh-2.3 - Improvement suggested by Niki Hansche */ + strcmp( cmd, "func" ) == 0 || + strcmp( cmd, "while" ) == 0) { /* ** If we hit another \do statement, then we want to @@ -674,7 +719,7 @@ static void cmd_do_sigint_cancel( sig, user_data ) { if (user_data != NULL) { - ct_cancel( (CS_CONNECTION*)user_data, (CS_COMMAND*)NULL, + ct_cancel( (CS_CONNECTION*)user_data, (CS_COMMAND*)NULL, CS_CANCEL_ATTN ); } sg_canceled = True; diff --git a/src/cmd_exit.c b/src/cmd_exit.c index 8010ca4..8e5d04e 100644 --- a/src/cmd_exit.c +++ b/src/cmd_exit.c @@ -30,7 +30,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_exit.c,v 1.3 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_exit.c,v 1.4 2012/03/14 09:17:51 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -43,6 +43,8 @@ int cmd_exit( argc, argv ) int argc ; char *argv[] ; { + int i; + /* * sqsh-2.1.7 - Feature to provide for an exit code. * @@ -65,6 +67,17 @@ int cmd_exit( argc, argv ) } } + /* + * sqsh-2.1.8 - Check if jobs are running that would otherwise be killed. + * If that is the case, show a message and continue the shell. + */ + for( i = 0; i < g_jobset->js_hsize; i++ ) { + if (g_jobset->js_jobs[i] != NULL) { + fprintf( stderr, "You have running jobs or pending job output\n" ) ; + return CMD_FAIL ; + } + } + return CMD_EXIT ; } diff --git a/src/cmd_for.c b/src/cmd_for.c index 915b400..a07504e 100644 --- a/src/cmd_for.c +++ b/src/cmd_for.c @@ -50,7 +50,6 @@ int cmd_for( argc, argv ) { varbuf_t *for_buf; int ret; - int exit_status; char *var_name; int i; diff --git a/src/cmd_func.c b/src/cmd_func.c index 1dcb4f4..5f52dfd 100644 --- a/src/cmd_func.c +++ b/src/cmd_func.c @@ -70,13 +70,12 @@ int cmd_func( argc, argv ) do_export = True; break; default : - fprintf( stderr, "\\func: -%c: Invalid option\n", - (int)ch ); + fprintf( stderr, "\\func: %s\n", sqsh_get_errstr()); have_error = True; } } - if ((argc - sqsh_optind) != 1) + if ( have_error || (argc - sqsh_optind) != 1) { fprintf( stderr, "Use: \\func [-x] <name>\n" ); fprintf( stderr, " <body>\n" ); @@ -181,8 +180,7 @@ int cmd_call( argc, argv ) if (f == NULL) { - fprintf( stderr, "\\call: Error calling %s: %s\n", - func_name ? (char*)func_name : "NULL", sqsh_get_errstr() ); + fprintf( stderr, "\\call: Error calling %s: %s\n", func_name ? (char*)func_name : "NULL", sqsh_get_errstr() ); return(CMD_FAIL); } diff --git a/src/cmd_go.c b/src/cmd_go.c index b68556f..84ce504 100644 --- a/src/cmd_go.c +++ b/src/cmd_go.c @@ -41,7 +41,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_go.c,v 1.4 2010/02/25 10:50:47 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: cmd_go.c,v 1.7 2014/03/11 21:49:04 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -78,6 +78,7 @@ int cmd_go( argc, argv ) char *repeat_batch; /* Dito. */ char *filter; /* Dito. */ char *filter_prog; /* Dito. */ + char *nosepline; /* Dito. */ char *sql; int sql_len; char pause_buf[5]; /* Buffer for "hit enter" */ @@ -121,7 +122,7 @@ int cmd_go( argc, argv ) fprintf( stderr, "\\go: Unbalanced comment tokens encountered\n" ); have_error = True; } - else while ((ch = sqsh_getopt( argc, argv, "nfhps:m:x;w:d:t;T:" )) != EOF) + else while ((ch = sqsh_getopt( argc, argv, "nfhps:m:x;w:d:t;T:el" )) != EOF) { switch (ch) { @@ -159,6 +160,14 @@ int cmd_go( argc, argv ) } break; + case 'e' : + if (env_put( g_env, "echo", "1", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\go: -e: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + case 'x' : dsp_flags |= DSP_F_X; @@ -174,6 +183,9 @@ int cmd_go( argc, argv ) case 'f' : dsp_flags |= DSP_F_NOFOOTERS; break; + case 'l' : + dsp_flags |= DSP_F_NOSEPLINE; + break; case 'm' : dsp_name = sqsh_optarg; break; @@ -218,11 +230,13 @@ int cmd_go( argc, argv ) if( (argc - sqsh_optind) > 1 || have_error) { fprintf( stderr, - "Use: \\go [-d display] [-h] [-f] [-n] [-p] [-m mode] [-s sec]\n" + "Use: \\go [-d display] [-e] [-h] [-f] [-l] [-n] [-p] [-m mode] [-s sec]\n" " [-t [filter]] [-w width] [-x [xgeom]] [-T title] [xacts]\n" " -d display When used with -x, send result to named display\n" + " -e Echo SQL buffer to output\n" " -h Suppress headers\n" " -f Suppress footers\n" + " -l Suppress line separators with pretty style output mode\n" " -n Do not expand variables\n" " -p Report runtime statistics\n" " -m mode Switch display mode for result set\n" @@ -306,14 +320,15 @@ int cmd_go( argc, argv ) * Retrieve any variables that may affect the way in which * we process or display data. */ - env_get( g_env, "headers", &headers ); - env_get( g_env, "footers", &footers ); - env_get( g_env, "echo", &echo ); - env_get( g_env, "expand", &expand ); - env_get( g_env, "statistics", &statistics ); - env_get( g_env, "clear_on_fail", &clear_on_fail ); - env_get( g_env, "batch_pause", &batch_pause ); - env_get( g_env, "filter", &filter ); + env_get( g_env, "batch_pause", &batch_pause ); + env_get( g_env, "clear_on_fail", &clear_on_fail ); + env_get( g_env, "echo", &echo ); + env_get( g_env, "expand", &expand ); + env_get( g_env, "filter", &filter ); + env_get( g_env, "footers", &footers ); + env_get( g_env, "headers", &headers ); + env_get( g_env, "nosepline", &nosepline ); + env_get( g_env, "statistics", &statistics ); /* * If the user didn't request for statistics via the flag, but @@ -322,10 +337,12 @@ int cmd_go( argc, argv ) if( show_stats == False && (statistics != NULL && *statistics == '1') ) show_stats = True; - if( !(dsp_flags & DSP_F_NOHEADERS) && headers != NULL && *headers == '0' ) + if( !(dsp_flags & DSP_F_NOHEADERS) && headers != NULL && *headers == '0' ) dsp_flags |= DSP_F_NOHEADERS; - if( !(dsp_flags & DSP_F_NOFOOTERS) && footers != NULL && *footers == '0' ) + if( !(dsp_flags & DSP_F_NOFOOTERS) && footers != NULL && *footers == '0' ) dsp_flags |= DSP_F_NOFOOTERS; + if( !(dsp_flags & DSP_F_NOSEPLINE) && nosepline != NULL && *nosepline == '1' ) + dsp_flags |= DSP_F_NOSEPLINE; /* diff --git a/src/cmd_history.c b/src/cmd_history.c index 0a3bd91..42d5579 100644 --- a/src/cmd_history.c +++ b/src/cmd_history.c @@ -35,7 +35,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_history.c,v 1.5 2010/02/25 10:50:47 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_history.c,v 1.9 2013/12/03 09:22:23 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -64,12 +64,14 @@ int cmd_history( argc, argv ) char dttm[32]; char hdrinfo[64]; char *datetime = NULL; + char *cp; + char fmt[64]; /* - * Initialize number of history buffers to show to the total number of - * available buffers. - */ + * Initialize number of history buffers to show to the total number of + * available buffers. + */ shownum = g_history->h_nitems; /* @@ -81,10 +83,7 @@ int cmd_history( argc, argv ) { case 'i' : show_info = True; - env_get( g_env, "datetime", &datetime); - if (datetime == NULL || datetime[0] == '\0' || (strcmp(datetime,"default") == 0)) - datetime = "%Y%m%d %H:%M:%S"; - break; + break; case 'x' : if ((shownum = atoi(sqsh_optarg)) <= 0) @@ -92,7 +91,7 @@ int cmd_history( argc, argv ) fprintf( stderr, "\\history: Invalid value for option -x (%s)\n", sqsh_optarg ); have_error = True; } - break; + break; default : fprintf( stderr, "\\history: %s\n", sqsh_get_errstr() ); @@ -115,6 +114,32 @@ int cmd_history( argc, argv ) } /* + * sqsh-2.2.0 - Since the datetime format string may contain [] to filter out seconds for + * smalldatetime datatypes, we have to remove these brackets here. Also replace the %u format + * specifier with 000 when specified in the format string. + * sqsh-2.5: Strip of .%q and [] from the datetime format string. + */ + if (show_info == True) + { + env_get( g_env, "datetime", &datetime); + if (datetime == NULL || *datetime == '\0' || (strcmp(datetime,"default") == 0)) + strcpy (fmt, "%Y%m%d %H:%M:%S"); + else + { + for (cp = fmt; *datetime != '\0'; datetime++) + { + if (*datetime == '.' && *(datetime+1) == '%' && *(datetime+2) == 'q') + { + datetime += 2; + } + else if (*datetime != '[' && *datetime != ']') + *cp++ = *datetime; + } + *cp = '\0'; + } + } + + /* * Since we want to print our history from oldest to newest we * will traverse the list backwards. Note, I don't like having * cmd_history() play with the internals of the history structure, @@ -130,19 +155,20 @@ int cmd_history( argc, argv ) line = hb->hb_buf ; while( (nl = strchr( line, '\n' )) != NULL ) { if( line == hb->hb_buf ) { - if (show_info == True) { - ts = localtime( &hb->hb_dttm ); - strftime( dttm, sizeof(dttm), datetime, ts ); - sprintf( hdrinfo, "(%2d - %2d/%s) ", - hb->hb_nbr, hb->hb_count, dttm ) ; + if (show_info == True) + { + ts = localtime( &hb->hb_dttm ); + strftime( dttm, sizeof(dttm), fmt, ts ); + sprintf( hdrinfo, "(%2d - %2d/%s) ", + hb->hb_nbr, hb->hb_count, dttm ) ; } else - sprintf( hdrinfo, "(%d) ", hb->hb_nbr ) ; + sprintf( hdrinfo, "(%d) ", hb->hb_nbr ) ; - printf( "%s%*.*s\n", hdrinfo, nl - line, nl - line, line ) ; + printf( "%s%*.*s\n", hdrinfo, (int) (nl - line), (int) (nl - line), line ) ; } else { - printf( "%*s%*.*s\n", strlen(hdrinfo), " ", nl - line, nl - line, line ) ; + printf( "%*s%*.*s\n", (int) strlen(hdrinfo), " ", (int) (nl - line), (int) (nl - line), line ) ; } line = nl + 1 ; @@ -152,7 +178,6 @@ int cmd_history( argc, argv ) printf( " %s\n", line ) ; } - return CMD_LEAVEBUF ; } @@ -176,51 +201,46 @@ int cmd_hist_load( argc, argv ) * Only one argument allowed. */ if( argc > 2 ) { - fprintf( stderr, "\\hist_load: Too many arguments; Use: \\hist_load [filename]\n" ) ; + fprintf( stderr, "\\hist-load: Too many arguments; Use: \\hist-load [filename]\n" ) ; return CMD_FAIL ; } + if (argc == 2) + history = argv[1]; + else + env_get( g_env, "history", &history ); + /* - * Check if the history has been created. + * Check if the history has been created and a history file is provided. */ - if (g_history != NULL) + if ( g_history != NULL && history != NULL && *history != '\0' ) { - if (argc == 2) - history = argv[1]; - else - env_get( g_env, "history", &history ); + exp_buf = varbuf_create( 512 ); - if ( history != NULL ) + if (exp_buf == NULL) { - exp_buf = varbuf_create( 512 ); - - if (exp_buf == NULL) + fprintf( stderr, "\\hist-load: %s\n", sqsh_get_errstr() ); + } + else + { + if (sqsh_expand( history, exp_buf, 0 ) == False) { - fprintf( stderr, "sqsh_exit: %s\n", sqsh_get_errstr() ); + fprintf( stderr, "\\hist-load: Error expanding $history: %s\n", + sqsh_get_errstr() ); } else { - if (sqsh_expand( history, exp_buf, 0 ) == False) - { - fprintf( stderr, "sqsh_exit: Error expanding $history: %s\n", - sqsh_get_errstr() ); - } + if (history_load( g_history, varbuf_getstr(exp_buf) ) == True) + fprintf( stdout, "\\hist-load - History buffer loaded from %s\n", + varbuf_getstr(exp_buf) ); else - { - if (history_load( g_history, varbuf_getstr(exp_buf) ) == True) - { - fprintf( stdout, "History buffer loaded from %s\n", - varbuf_getstr(exp_buf) ); - sprintf( str, "%d", history_get_nbr(g_history) ); - env_set( g_env, "histnum", str ); - } - else - fprintf( stdout, "Failed to load history from %s\n", - varbuf_getstr(exp_buf) ); + fprintf( stderr, "\\hist-load - Error: Failed to load history from %s\n", + varbuf_getstr(exp_buf) ); - } - varbuf_destroy( exp_buf ); + sprintf( str, "%d", history_get_nbr(g_history) ); + env_set( g_env, "histnum", str ); } + varbuf_destroy( exp_buf ); } } return CMD_LEAVEBUF ; @@ -237,6 +257,7 @@ int cmd_hist_save( argc, argv ) int argc ; char *argv[] ; { + char str[16]; char *history; varbuf_t *exp_buf; @@ -245,45 +266,47 @@ int cmd_hist_save( argc, argv ) * Only one argument allowed. */ if( argc > 2 ) { - fprintf( stderr, "\\hist_save: Too many arguments; Use: \\hist_save [filename]\n" ) ; + fprintf( stderr, "\\hist-save: Too many arguments; Use: \\hist-save [filename]\n" ) ; return CMD_FAIL ; } + if (argc == 2) + history = argv[1]; + else + env_get( g_env, "history", &history ); + /* - * If the history has been created, and it contains items, - * then we write the history out to a file. + * If the history has been created, and it contains items, and a history file is provided + * then we write the history out to this file. */ - if (g_history != NULL) + if ( g_history != NULL && history != NULL && *history != '\0' && history_get_nitems( g_history ) > 0 ) { - if (argc == 2) - history = argv[1]; - else - env_get( g_env, "history", &history ); + exp_buf = varbuf_create( 512 ); - if (history != NULL && history_get_nitems( g_history ) > 0) + if (exp_buf == NULL) { - exp_buf = varbuf_create( 512 ); - - if (exp_buf == NULL) + fprintf( stderr, "\\hist-save: %s\n", sqsh_get_errstr() ); + } + else + { + if (sqsh_expand( history, exp_buf, 0 ) == False) { - fprintf( stderr, "sqsh_exit: %s\n", sqsh_get_errstr() ); + fprintf( stderr, "\\hist-save: Error expanding $history: %s\n", + sqsh_get_errstr() ); } else { - if (sqsh_expand( history, exp_buf, 0 ) == False) - { - fprintf( stderr, "sqsh_exit: Error expanding $history: %s\n", - sqsh_get_errstr() ); - } + if (history_save( g_history, varbuf_getstr(exp_buf) ) == True) + fprintf( stdout, "\\hist-save - History buffer saved to %s\n", + varbuf_getstr(exp_buf) ); else - { - if (history_save( g_history, varbuf_getstr(exp_buf) ) == True) - fprintf( stdout, "History buffer saved to %s\n", - varbuf_getstr(exp_buf) ); + fprintf( stderr, "\\hist-save - Error: Failed to write history to %s\n", + varbuf_getstr(exp_buf) ); - } - varbuf_destroy( exp_buf ); + sprintf( str, "%d", history_get_nbr(g_history) ); + env_set( g_env, "histnum", str ); } + varbuf_destroy( exp_buf ); } } return CMD_LEAVEBUF ; diff --git a/src/cmd_if.c b/src/cmd_if.c index 59ba367..38579ca 100644 --- a/src/cmd_if.c +++ b/src/cmd_if.c @@ -180,7 +180,6 @@ int cmd_if_exec( argc, argv, exit_status ) pid_t ret_pid; int status; char nbr[16]; - int ret; func_t *f; char *return_str; @@ -233,7 +232,7 @@ int cmd_if_exec( argc, argv, exit_status ) case -1: fprintf( stderr, "\\if: fork() call failed: %s\n", strerror(errno) ); - env_set( g_internal_env, "$?", "-1" ); + env_set( g_internal_env, "?", "-1" ); sig_restore(); return(CMD_FAIL); @@ -264,7 +263,7 @@ int cmd_if_exec( argc, argv, exit_status ) fprintf( stderr, "\\if: Error from waitpid(): %s\n", strerror(errno) ); - env_set( g_internal_env, "$?", "-1" ); + env_set( g_internal_env, "?", "-1" ); sig_restore(); return(CMD_FAIL); } @@ -279,7 +278,7 @@ int cmd_if_exec( argc, argv, exit_status ) } sprintf( nbr, "%d", *exit_status ); - env_set( g_internal_env, "$?", nbr ); + env_set( g_internal_env, "?", nbr ); break; } @@ -468,6 +467,15 @@ int cmd_if_input( if_buf, else_buf ) } prompt_indent[i] = '\0'; env_put( g_env, "prompt_indent", prompt_indent, ENV_F_TRAN ); + + /* + ** Bugfix sqsh-2.1.8 + ** Copy the nested new 'if' into the current buffer. + */ + if (parse_state == STATE_IF) + varbuf_strcat( if_buf, str ); + else + varbuf_strcat( else_buf, str ); } else if (strcmp( cmd, "elif" ) == 0 && nesting_level == 1) diff --git a/src/cmd_input.c b/src/cmd_input.c index 6fc34ce..60bf67c 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.5 2010/01/28 15:30:37 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: cmd_input.c,v 1.9 2013/07/20 16:18:35 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -60,6 +60,11 @@ USE(RCS_Id) static void input_sigint_jmp _ANSI_ARGS(( int, void* )); static char* input_strchr _ANSI_ARGS(( varbuf_t*, char*, int )); static int input_read _ANSI_ARGS(( varbuf_t*, int )); +#if defined(USE_READLINE) +static int DynKeywordLoad _ANSI_ARGS(( void )); /* sqsh-2.1.8 - Feature dynamic keyword load */ +#endif +/* sqsh-2.3 - Check if we currently are in a C style comment in the SQL buffer */ +static int csc_buffer _ANSI_ARGS(( varbuf_t* )); /* * The following macro is used to determine if a line of input is @@ -71,8 +76,8 @@ static int input_read _ANSI_ARGS(( varbuf_t*, int )); /* - * 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. */ @@ -110,12 +115,15 @@ int cmd_input() char *newline_go ; /* Value of $newline_go */ char *history_shorthand ; /* Value of $history_shorthand */ char *lineno ; /* Value of $lineno */ +#if defined(USE_READLINE) + char *keyword_dynamic ; /* Value of $keyword_dynamic */ + char *keyword_refresh ; /* Value of $keyword_refresh */ +#endif /*-- Misc --*/ 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 */ @@ -127,6 +135,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 @@ -229,37 +242,68 @@ int cmd_input() */ for (;;) { - no_hist = False; /* Save history for this buffer */ - +#if defined(USE_READLINE) /* - * Clear out the buffer that will be used to place input read - * from the user. + * sqsh-2.1.8 - Feature dynamic keyword load + * If we are in interactive mode and we have keyword_dynamic enabled + * then we want to do a refresh of the keyword list when the database + * context is changed, i.e. a "use <database>" command was executed. */ - varbuf_clear( read_buf ); + env_get( g_env, "keyword_dynamic", &keyword_dynamic ); + env_get( g_internal_env, "keyword_refresh", &keyword_refresh ); + if (interactive && + keyword_refresh != NULL && *keyword_refresh != '0' && + keyword_dynamic != NULL && *keyword_dynamic != '0') + { + (void) DynKeywordLoad(); + env_set( g_internal_env, "keyword_refresh", "0" ); + } +#endif /* - * 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. + * 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. */ - ret = input_read( read_buf, interactive ); - - if (ret <= 0) + if (str_remainder != NULL) { - if (ret == 0) + 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 (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. @@ -276,7 +320,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))) { @@ -316,50 +360,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' ); - str = varbuf_getstr( sg_buf ); + /* + * We now have an extra line. + */ + env_set( g_env, "lineno", "+1" ); + } + + /* + * 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; } @@ -449,7 +536,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) ); @@ -463,8 +550,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 */ @@ -505,7 +592,6 @@ int cmd_input() case CMD_ABORT : goto loop_abort; break; - default : sprintf( number, "=%d", cur_lineno ); @@ -521,7 +607,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) @@ -529,14 +615,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 */ } @@ -551,7 +634,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) { /* @@ -649,7 +732,7 @@ loop_done : if (read_buf != NULL) varbuf_destroy( read_buf ); - + /* * Restore the line number to its previous value. */ @@ -667,7 +750,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 @@ -700,7 +783,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) @@ -708,7 +791,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) { @@ -736,13 +819,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 = "--> "; } @@ -755,7 +838,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 @@ -790,8 +873,12 @@ static int input_read( output_buf, interactive ) * table name, [_0-9A-Za-z]. If we hit a comment, then we * simply ignore this line, without even incrementing the * line number. + * sqsh-2.3 - Only ignore sqsh # comments if the current + * SQL buffer did not start a C style comment construct, + * that is not closed so far, and if we are not inside a + * single or double quotes string. */ - if (IS_COMMENT(str)) + if (IS_COMMENT(str) && csc_buffer( g_sqlbuf ) == 0) { if (is_continued) { @@ -873,13 +960,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; @@ -897,28 +984,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; } @@ -935,13 +1022,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; @@ -959,28 +1046,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; } @@ -992,6 +1079,120 @@ static char* input_strchr( varbuf, str, c ) } /* + * csc_buffer(): + * + * sqsh-2.3 - Blast through the SQL buffer that is created up + * till now and see if we are in a quoted or double + * quoted string or in a C style comment. + * Return the value of the quote_type that reflects the + * current situation. (0 means not in quotes or comments) + */ +static int csc_buffer( varbuf ) + varbuf_t *varbuf; +{ +#define QUOTE_NONE 0 +#define QUOTE_SINGLE 1 +#define QUOTE_DOUBLE 2 +#define QUOTE_COMMENT 3 + + char *cptr; + int quote_type = QUOTE_NONE; + int csclevel = 0; + + + if ( (cptr = varbuf_getstr(varbuf)) == NULL ) + return QUOTE_NONE; + + /*-- Blast through varbuf --*/ + for (; *cptr != '\0'; ++cptr) + { + /* + * First step over any escape characters and the character + * that is escaped by \\ itself, but still do a sanity + * check on end of string altogether. + */ + if (*cptr == '\\' && *(cptr + 1) == '\\') + { + cptr += 3; + if (*cptr == '\0' || *(cptr - 1) == '\0') + break; + } + + switch (quote_type) + { + case QUOTE_NONE: + switch (*cptr) + { + case '\'': + quote_type = QUOTE_SINGLE; + break; + case '\"': + quote_type = QUOTE_DOUBLE; + break; + case '/' : + if (*(cptr + 1) == '*') + { + quote_type = QUOTE_COMMENT; + ++csclevel; + ++cptr; + } + break; + case '-': /* -- comment till end of end line */ + if (*(cptr + 1) == '-') + { + while (*cptr != '\n' && *cptr != '\0') + ++cptr; + + if (*cptr == '\0') + --cptr; + } + break; + default: + break; + } + break; + + case QUOTE_COMMENT: + /* + * C style comments in SQL may be nested, but do not + * take quoting or -- comments in account anymore. + * This is according to isql behavior. + */ + if (*cptr == '/' && *(cptr + 1) == '*') + { + ++cptr; + ++csclevel; + } + else if (*cptr == '*' && *(cptr + 1) == '/') + { + ++cptr; + if (--csclevel == 0) + 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; + } + } + return quote_type; +} + +/* * input_sigint_jmp(): * * Used to catch ^C's from the user. If there is currently a database @@ -1003,3 +1204,140 @@ static void input_sigint_jmp( sig, user_data ) { LONGJMP( sg_jmp_buf, 1 ); } + +#if defined(USE_READLINE) +/* + * Function: DynKeywordLoad() + * + * sqsh-2.1.8 - Dynamically execute a query provided by the variable keyword_query + * and load the result set into the readline autocompletion list. + * By default the query is "select name from sysobjects order by name" + * But of course you can change this to anything you like as long as the result set + * contains a first column with character data. The variable keyword_query can be + * defined in your .sqshrc file for example or in a sqsh_session file. + * + */ +static int DynKeywordLoad () +{ + CS_COMMAND *cmd; + CS_CHAR *keyword_query; + CS_DATAFMT columns[1]; + CS_RETCODE ret; + CS_RETCODE results_ret; + CS_INT result_type; + CS_INT count; + CS_INT idx; + CS_INT datalength[1]; + CS_SMALLINT indicator [1]; + CS_CHAR name [256]; + + + env_get( g_env, "keyword_query", &keyword_query ); + if ( keyword_query == NULL || *keyword_query == '\0' ) { + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Variable keyword_query is empty.\n")); + return (CS_FAIL); + } + if ( g_connection == NULL ) + { + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: g_connection is not initialized.\n")); + return (CS_FAIL); + } + if (ct_cmd_alloc( g_connection, &cmd ) != CS_SUCCEED) + { + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Call to ct_cmd_alloc failed.\n")); + return (CS_FAIL); + } + if (ct_command( cmd, /* Command Structure */ + CS_LANG_CMD, /* Command Type */ + keyword_query, /* Buffer */ + CS_NULLTERM, /* Buffer Length */ + CS_UNUSED /* Options */ + ) != 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) + { + ct_cmd_drop( cmd ); + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Call to ct_send failed.\n")); + return (CS_FAIL); + } + + (void) sqsh_readline_clear(); /* Empty the current keyword list */ + (void) sqsh_readline_load (); /* Reload keywords from $keyword_file */ + + while ((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED) + { + switch ((int) result_type) + { + case CS_ROW_RESULT: + columns[0].datatype = CS_CHAR_TYPE; + columns[0].format = CS_FMT_NULLTERM; + columns[0].maxlength = 255; + columns[0].count = 1; + columns[0].locale = NULL; + ct_bind(cmd, 1, &columns[0], name, &datalength[0], &indicator[0]); + + while ( ct_fetch (cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count) == CS_SUCCEED ) + { + /* Remove trailing blanks, tabs and newlines, just in case */ + for ( idx = strlen(name) - 1; + idx >= 0 && (name[idx] == ' ' || name[idx] == '\t' || name[idx] == '\n'); + name[idx--] = '\0'); + sqsh_readline_add (name); /* Add name to readline linked list of keywords */ + } + break; + + case CS_COMPUTE_RESULT: + case CS_CURSOR_RESULT: + case CS_MSG_RESULT: + case CS_PARAM_RESULT: + case CS_STATUS_RESULT: + /* + * Just ignore these kind of results. + */ + while ( ct_fetch (cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count) == CS_SUCCEED ); + break; + + case CS_CMD_SUCCEED: + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: No rows returned from query.\n")); + ret = CS_FAIL; + break; + + case CS_CMD_FAIL: + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Error encountered during query processing.\n")); + ret = CS_FAIL; + break; + + case CS_CMD_DONE: + break; + + default: + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Unexpected error encountered. (1)\n")); + ret = CS_FAIL; + break; + } + } + + switch ((int) results_ret) + { + case CS_END_RESULTS: + ret = CS_SUCCEED; + break; + + case CS_FAIL: + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Unexpected error encountered. (2)\n")); + ret = CS_FAIL; + break; + + default: + DBG(sqsh_debug(DEBUG_ERROR, "DynKeywordLoad: Unexpected error encountered. (3)\n")); + ret = CS_FAIL; + break; + } + ct_cmd_drop( cmd ); + return ( ret ); +} +#endif diff --git a/src/cmd_jobs.c b/src/cmd_jobs.c index 7a62a64..a9a2cc9 100644 --- a/src/cmd_jobs.c +++ b/src/cmd_jobs.c @@ -31,7 +31,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_jobs.c,v 1.2 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_jobs.c,v 1.3 2013/04/04 10:52:35 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -82,7 +82,7 @@ int cmd_jobs( argc, argv ) printf( "\tFlags : %d\n", j->job_flags ) ; printf( "\tOutput : %s\n", j->job_output ) ; printf( "\tStatus : %d\n", j->job_status ) ; - printf( "\tChild pid: %d\n", j->job_pid ) ; + printf( "\tChild pid: %d\n", (int) j->job_pid ) ; } } } diff --git a/src/cmd_lock.c b/src/cmd_lock.c index ad9ea3c..3c8edca 100644 --- a/src/cmd_lock.c +++ b/src/cmd_lock.c @@ -40,7 +40,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_lock.c,v 1.1.1.1 2004/04/07 12:35:03 chunkm0nkey Exp $"; +static char RCS_Id[] = "$Id: cmd_lock.c,v 1.2 2013/04/04 10:52:35 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -48,13 +48,14 @@ int cmd_lock( argc, argv ) int argc ; char *argv[] ; { +#if defined(HAVE_CRYPT) #if defined(HAVE_SHADOW_H) - struct spwd *spwd; + struct spwd *spwd; +#endif + char *crypt_pass; #endif struct passwd *passwd; - char salt[2]; char pass[25]; - char *crypt_pass; char *real_pass = NULL; int len; @@ -85,7 +86,7 @@ int cmd_lock( argc, argv ) #if defined(HAVE_SHADOW_H) /* * If the passwd->pw_passwd entry is undefined or contains an invalid - * password (e.g. "x"), the we are probably using shadow passwords, + * password (e.g. "x"), then we are probably using shadow passwords, * so lets give that a try. */ if (real_pass == NULL || strlen(real_pass) < 2) { @@ -145,10 +146,7 @@ int cmd_lock( argc, argv ) return CMD_LEAVEBUF; #if defined(HAVE_CRYPT) - salt[0] = real_pass[0]; - salt[1] = real_pass[1]; - - crypt_pass = (char*)crypt( pass, salt ); + crypt_pass = (char*)crypt( pass, real_pass ); if (strcmp( real_pass, crypt_pass ) != 0) { fprintf( stderr, "sqsh: Invalid password.\n" ); diff --git a/src/cmd_loop.c b/src/cmd_loop.c index 17ecc76..68c4c0d 100644 --- a/src/cmd_loop.c +++ b/src/cmd_loop.c @@ -39,7 +39,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_loop.c,v 1.1.1.1 2004/04/07 12:35:03 chunkm0nkey Exp $"; +static char RCS_Id[] = "$Id: cmd_loop.c,v 1.2 2013/04/18 11:54:43 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -50,7 +50,7 @@ int cmd_loop( argc, argv ) int argc; char *argv[]; { - FILE *input_file ; /* Where input is coming from */ + FILE *input_file = NULL; /* Where input is coming from */ int ret; int exit_status; @@ -195,7 +195,7 @@ int cmd_loop( argc, argv ) * If we opened a file to read, then close it. There is a brief period * here where an interrupt could trash us, but lets hope for the best. */ - if (file_name != NULL) + if (input_file != NULL) { /* * Let the stdin be what it used to be. diff --git a/src/cmd_misc.c b/src/cmd_misc.c index bd0ead5..6af2760 100644 --- a/src/cmd_misc.c +++ b/src/cmd_misc.c @@ -35,7 +35,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_misc.c,v 1.2 2009/04/14 10:02:54 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_misc.c,v 1.3 2013/04/04 10:52:35 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -89,8 +89,8 @@ int cmd_display( sqlbuf ) /*-- Print the line of text --*/ fprintf( stdout, "%s%*.*s\n", s, /* Prompt */ - end - buf, /* Length of line */ - end - buf, /* Length of line */ + (int) (end - buf), /* Length of line */ + (int) (end - buf), /* Length of line */ buf ) ; /* Line itself */ fflush( stdout ) ; diff --git a/src/cmd_read.c b/src/cmd_read.c index e9b8de2..61889a5 100644 --- a/src/cmd_read.c +++ b/src/cmd_read.c @@ -35,7 +35,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_read.c,v 1.4 2004/11/05 13:01:14 mpeppler Exp $"; +static char RCS_Id[] = "$Id: cmd_read.c,v 1.5 2013/04/29 15:48:33 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -82,7 +82,7 @@ int cmd_read( argc, argv ) } /* - * There should only be on more argument left on the command line, + * There should only be one more argument left on the command line, * so if there are more, or if an error was found above, then * print out a usage message. */ @@ -93,7 +93,7 @@ int cmd_read( argc, argv ) var_name = argv[sqsh_optind]; - if (hide_output == True) + if ( hide_output == True && isatty(fileno(stdin)) ) { r = sqsh_getinput( "", input, sizeof(input), 0 ); if (r < 0) @@ -107,46 +107,10 @@ int cmd_read( argc, argv ) } else { - /* If stdin is a tty then simply read from stdin. - If stdin is NOT a tty (e.g. redirected via < ) - then open the tty for reading, and then close it again. - */ - if(sqsh_stdin_isatty()) { - if (fgets( input, sizeof(input), stdin ) == NULL) - { - fprintf( stderr, "\\read: %s\n", strerror(errno) ); - return CMD_FAIL; - } - } else { - char *tty_name; - FILE *fin; - - tty_name = ctermid(NULL); - if (tty_name == NULL) { - sqsh_set_error( SQSH_E_EXIST, - "cmd_read: Unable to determine controlling tty" ); - return CMD_FAIL; - } - - fin = fopen("/dev/tty", "r"); - if (!fin) { - fprintf( stderr, "\\read: %s\n", strerror(errno) ); - return CMD_FAIL; - } - if (fgets( input, sizeof(input), fin ) == NULL) - { - fprintf( stderr, "\\read: %s\n", strerror(errno) ); - fclose(fin); - return CMD_FAIL; - } - fclose(fin); - } - - str = strchr( input, '\n' ); - - if (str != NULL) + if (fgets( input, sizeof(input), stdin ) == NULL) { - str = '\0'; + fprintf( stderr, "\\read: %s\n", strerror(errno) ); + return CMD_FAIL; } } diff --git a/src/cmd_reconnect.c b/src/cmd_reconnect.c index c5d2990..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.1.1.1 2004/04/07 12:35:02 chunkm0nkey 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,24 +39,37 @@ 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 ; } - ct_close( old_connection, CS_FORCE_CLOSE ); + if (ct_close( old_connection, CS_UNUSED ) != CS_SUCCEED) + 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/cmd_reset.c b/src/cmd_reset.c index 703f748..45ac4b2 100644 --- a/src/cmd_reset.c +++ b/src/cmd_reset.c @@ -28,13 +28,17 @@ #include "sqsh_env.h" #include "sqsh_cmd.h" #include "cmd.h" +#if defined(USE_READLINE) +#include "sqsh_readline.h" +#endif /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_reset.c,v 1.2 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: cmd_reset.c,v 1.3 2013/04/04 10:52:35 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ + /* * cmd_clear: * @@ -50,8 +54,9 @@ int cmd_clear( argc, argv ) return CMD_FAIL ; } #if defined(USE_READLINE) - if (g_interactive) - _rl_clear_screen(); + if (g_interactive) { + _rl_clear_screen (); + } #endif return CMD_CLEARBUF ; } diff --git a/src/cmd_run.c b/src/cmd_run.c new file mode 100644 index 0000000..94186ce --- /dev/null +++ b/src/cmd_run.c @@ -0,0 +1,230 @@ +/* + * cmd_run.c - Execute a batch file from the prompt + * + * Copyright (C) 2014 by Martin Wesdorp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, write to the Free Software + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include <stdio.h> +#include "sqsh_config.h" +#include "sqsh_global.h" +#include "sqsh_varbuf.h" +#include "sqsh_env.h" +#include "sqsh_error.h" +#include "sqsh_cmd.h" +#include "sqsh_job.h" +#include "sqsh_getopt.h" +#include "sqsh_readline.h" +#include "sqsh_stdin.h" +#include "cmd.h" +#include "cmd_misc.h" +#include "cmd_input.h" + +/*-- Current Version --*/ +#if !defined(lint) && !defined(__LINT__) +static char RCS_Id[] = "$Id: cmd_run.c,v 1.5 2014/03/11 21:49:04 mwesdorp Exp $"; +USE(RCS_Id) +#endif /* !defined(lint) */ + +/* + * cmd_run(): + */ +int cmd_run( argc, argv ) + int argc; + char *argv[]; +{ + FILE *input_file = NULL; /* Where input is coming from */ + int fn_optind; /* argv index of filename argument */ + char *swap_ptr; /* Used for swapping strings */ + int exit_status; + + /*-- Variables settable by command line options --*/ + char *file_name = NULL; + int have_error = False; + + /*-- Variables required by sqsh_getopt --*/ + int c; + extern int sqsh_optind; + extern char *sqsh_optarg; + + + /* + * Open global environment transaction + */ + env_tran( g_env ); + + /* + * Parse the command line options. + */ + while ((c = sqsh_getopt( argc, argv, "efhlnpm:i:" )) != EOF) + { + switch (c) + { + case 'e' : + if (env_put( g_env, "echo", "1", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -e: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'f' : + if (env_put( g_env, "footers", "0", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -f: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'h' : + if (env_put( g_env, "headers", "0", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -h: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'l' : + if (env_put( g_env, "nosepline", "1", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -l: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'n' : + if (env_put( g_env, "expand", "0", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -n: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'p' : + if (env_put( g_env, "statistics", "1", ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -p: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'm' : + if (env_put( g_env, "style", sqsh_optarg, ENV_F_TRAN ) == False) + { + fprintf( stderr, "\\run: -m: %s\n", sqsh_get_errstr() ); + have_error = True; + } + break; + + case 'i' : + file_name = sqsh_optarg; + break; + + default : + fprintf(stderr, "\\run: %s\n", sqsh_get_errstr() ); + have_error = True; + } + } + + /* + * Check that a file is provided. + */ + if( file_name == NULL || have_error ) + { + fprintf( stderr, "Use: \\run [-e] [-f] [-h] [-n] [-p] [-m style] -i filename [optional script parameters ...]\n" ); + fprintf( stderr, " -e Run the script file with echo on\n" ); + fprintf( stderr, " -f Suppress footers\n" ); + fprintf( stderr, " -h Suppress headers\n" ); + fprintf( stderr, " -l Suppress separator lines with pretty output\n" ); + fprintf( stderr, " -n Disable SQL buffer variable expansion\n" ); + fprintf( stderr, " -p Report runtime statistics\n" ); + fprintf( stderr, " -m style Specify output style {bcp|csv|horiz|html|meta|none|pretty|vert}\n" ); + fprintf( stderr, " -i filename SQL file to run\n" ); + env_rollback( g_env ); + return CMD_FAIL; + } + + /* + * If there are any arguments left on the command line, they need to be put on the + * argument stack. Make sure that the new argv[0] on the stack points to the filename. + */ + for ( fn_optind = 0; fn_optind < argc && argv[fn_optind] != file_name; fn_optind++ ); + if (sqsh_optind-1 != fn_optind) + { + swap_ptr = argv[sqsh_optind-1]; + argv[sqsh_optind-1] = file_name; + argv[fn_optind] = swap_ptr; + } + g_func_args[g_func_nargs].argc = argc - sqsh_optind + 1; + g_func_args[g_func_nargs].argv = &(argv[sqsh_optind-1]); + g_func_nargs++; + + /* + * Open the file for input and make it stdin. + */ + if ((input_file = fopen( (char*) file_name, "r" )) == NULL) + { + fprintf( stderr, "\\run: %s: %s\n", (char*) file_name, strerror( errno ) ); + g_func_nargs--; + env_rollback( g_env ); + return CMD_FAIL; + } + env_put ( g_env, "script", file_name, ENV_F_TRAN); + sqsh_stdin_file( input_file ); + + /* + * Make sure we have a valid connection. + */ + if ((jobset_run( g_jobset, "\\connect", &exit_status )) == -1 || exit_status == CMD_FAIL) + { + fprintf( stderr, "\\run: Unable to (re)connect\n" ); + sqsh_stdin_pop(); + fclose( input_file ); + g_func_nargs--; + env_rollback( g_env ); + return CMD_FAIL; + } + + /* + * Start processing the batch file. Ignore the return value. + */ + (void) cmd_input(); + + /* + * Pop the argument stack. + * Reset stdin to what it used to be. + * Close the open batch file. + * Rollback the global environment to its original state. + */ + sqsh_stdin_pop(); + fclose( input_file ); + g_func_nargs--; + env_rollback( g_env ); + + /* + * Set appropriate return and exit values. + * If script used \exit, then $exit_value may be set and we need to assign this value to $?. + * If \return was used, then "$?" may already be set and we can leave it that way. + */ + env_get ( g_env, "exit_value", &swap_ptr ); + if (*swap_ptr != '0' ) + { + env_set ( g_internal_env, "?", swap_ptr ); + env_set ( g_env, "exit_value", "0" ); + } + + return CMD_LEAVEBUF; +} diff --git a/src/cmd_shell.c b/src/cmd_shell.c index f5c3c51..1c94c99 100644 --- a/src/cmd_shell.c +++ b/src/cmd_shell.c @@ -32,7 +32,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: cmd_shell.c,v 1.1.1.1 2004/04/07 12:35:05 chunkm0nkey Exp $"; +static char RCS_Id[] = "$Id: cmd_shell.c,v 1.3 2014/03/11 21:49:04 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -110,3 +110,87 @@ int cmd_shell( argc, argv ) return CMD_LEAVEBUF; } + +/* + * cmd_lcd: Change local working directory. + * sqsh-2.5 - New feature. + */ +int cmd_lcd( argc, argv ) + int argc; + char *argv[]; +{ + int ret; /* Return value */ + char tmp[512] = ""; /* Tmp storage area */ + static char owd[512] = ""; /* Old working directory (previous) */ + char *sp; /* String pointer */ + + + if (argc != 2) + { + fprintf( stderr, "Use: \\lcd dir_name\n" ); + env_set ( g_internal_env, "?", "1" ); + return CMD_FAIL; + } + + sp = getcwd ( tmp, sizeof(tmp) ); + sp = ( strcmp ( argv[1], "-" ) == 0 && owd[0] != '\0' ) ? owd : argv[1]; + ret = chdir ( sp ); + if (ret != 0) + { + fprintf( stderr, "\\lcd: %s: %s\n", (char*) sp, strerror( errno ) ); + env_set ( g_internal_env, "?", "1" ); + return CMD_FAIL; + } + else + fprintf( stdout, "\\lcd: local directory changed to: %s\n", sp ); + + strcpy (owd, tmp); + env_set ( g_internal_env, "?", "0" ); + return CMD_LEAVEBUF; +} + +/* + * cmd_pwd: Print current working directory. + * sqsh-2.5 - New feature. + */ +int cmd_pwd( argc, argv ) + int argc; + char *argv[]; +{ + char pwd[512]; + + if (argc != 1) + { + fprintf( stderr, "Use: \\pwd\n" ); + env_set ( g_internal_env, "?", "1" ); + return CMD_FAIL; + } + + fprintf( stdout, "%s\n", getcwd( pwd, sizeof(pwd) ) ); + env_set ( g_internal_env, "?", "0" ); + return CMD_LEAVEBUF; +} + +/* + * cmd_ls: Show files in current directory. + * sqsh-2.5 - New feature. + */ +int cmd_ls( argc, argv ) + int argc; + char *argv[]; +{ + char return_value[10]; + int exit_status; + + if (argc != 1) + { + fprintf( stderr, "Use: \\ls\n" ); + env_set ( g_internal_env, "?", "1" ); + return CMD_FAIL; + } + + exit_status = system ( "ls" ); + sprintf (return_value, "%d", exit_status); + env_set ( g_internal_env, "?", return_value ); + return CMD_LEAVEBUF; +} diff --git a/src/config.h b/src/config.h deleted file mode 100644 index 2932b93..0000000 --- a/src/config.h +++ /dev/null @@ -1,85 +0,0 @@ -/* src/config.h. Generated by configure. */ -#ifndef config_h_included -#define config_h_included - -/* - * Define the following if you compiler is an ANSI compiler and supports - * prototypes, etl a. - */ -#define STDC_HEADERS 1 - -/* - * The include file sys/wait.h is required by sqsh_sigcld.c in order - * to call wait_pid(). Define this if the header file is available. - */ -#define HAVE_SYS_WAIT_H 1 - -/* - * Common header files. - */ -#define HAVE_STDLIB_H 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_STRING_H 1 -#define HAVE_FCNTL_H 1 -#define HAVE_UNISTD_H 1 -#define HAVE_MEMORY_H 1 -#define HAVE_ERRNO_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_TIME_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_LIMITS_H 1 -#define HAVE_CRYPT_H 1 -#define HAVE_SHADOW_H 1 -#define HAVE_STROPTS_H 1 - -/* - * If you compiler doesn't fully support the keyword 'const' - * then define const to be empty. - */ -/* #undef const */ - -/* - * If the following types are not defined in stdlib.h and sys/types.h - * then guess the closest possible data type. - */ -/* #undef mode_t */ -/* #undef pid_t */ -/* #undef uid_t */ - -/* - * The following is the return type of a signal handler. On most - * systems this is void. - */ -#define RETSIGTYPE void - -/* - * The following functions are frequently unavailable on certain - * systems. - */ -#define HAVE_STRCASECMP 1 -#define HAVE_STRERROR 1 -/* #undef HAVE_CFTIME */ -#define HAVE_STRFTIME 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_LOCALTIME 1 -#define HAVE_TIMELOCAL 1 -#define HAVE_STRCHR 1 -#define HAVE_SIGSETJMP 1 -#define HAVE_GETTIMEOFDAY 1 -/* #undef HAVE_GET_PROCESS_STATS */ -#define HAVE_SIGACTION 1 -/* #undef HAVE_CRYPT */ -#define HAVE_POLL 1 - -/* - * Define if your compiler supports the volatile keyword. - */ -#define HAVE_VOLATILE 1 - -/* - * Signal behaviour - */ -/* #undef SYSV_SIGNALS */ - -#endif diff --git a/src/config.h.in b/src/config.h.in index 87cab22..aa2abc0 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -1,154 +1,91 @@ -/* src/config.h.in. Generated from configure.in by autoheader. */ +#ifndef config_h_included +#define config_h_included -/* Define to 1 if you have the `cftime' function. */ -#undef HAVE_CFTIME - -/* Define to 1 if you have the `crypt' function. */ -#undef HAVE_CRYPT - -/* Define to 1 if you have the <crypt.h> header file. */ -#undef HAVE_CRYPT_H +/* + * Define the following if you compiler is an ANSI compiler and supports + * prototypes, etl a. + */ +#undef STDC_HEADERS -/* Define to 1 if you have the <errno.h> header file. */ -#undef HAVE_ERRNO_H +/* + * The include file sys/wait.h is required by sqsh_sigcld.c in order + * to call wait_pid(). Define this if the header file is available. + */ +#undef HAVE_SYS_WAIT_H -/* Define to 1 if you have the <fcntl.h> header file. */ +/* + * Common header files. + */ +#undef HAVE_STDLIB_H +#undef HAVE_SYS_TYPES_H +#undef HAVE_STRING_H #undef HAVE_FCNTL_H - -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY - -/* Define to 1 if you have the `get_process_stats' function. */ -#undef HAVE_GET_PROCESS_STATS - -/* Define to 1 if you have the <inttypes.h> header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the <limits.h> header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the <locale.h> header file. */ -#undef HAVE_LOCALE_H - -/* Define to 1 if you have the `localtime' function. */ -#undef HAVE_LOCALTIME - -/* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - -/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_UNISTD_H #undef HAVE_MEMORY_H - -/* Define to 1 if you have the `poll' function. */ -#undef HAVE_POLL - -/* Define to 1 if you have the `setlocale' function. */ -#undef HAVE_SETLOCALE - -/* Define to 1 if you have the <shadow.h> header file. */ +#undef HAVE_ERRNO_H +#undef HAVE_SYS_TIME_H +#undef HAVE_TIME_H +#undef HAVE_SYS_PARAM_H +#undef HAVE_LIMITS_H +#undef HAVE_CRYPT_H #undef HAVE_SHADOW_H +#undef HAVE_STROPTS_H -/* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION - -/* Define to 1 if your environment provides sigsetjpm() */ -#undef HAVE_SIGSETJMP +/* + * If you compiler doesn't fully support the keyword 'const' + * then define const to be empty. + */ +#undef const -/* Define to 1 if you have the <stdint.h> header file. */ -#undef HAVE_STDINT_H +/* + * If the following types are not defined in stdlib.h and sys/types.h + * then guess the closest possible data type. + */ +#undef mode_t +#undef pid_t +#undef uid_t -/* Define to 1 if you have the <stdlib.h> header file. */ -#undef HAVE_STDLIB_H +/* + * The following is the return type of a signal handler. On most + * systems this is void. + */ +#undef RETSIGTYPE -/* Define to 1 if you have the `strcasecmp' function. */ +/* + * The following functions are frequently unavailable on certain + * systems. + */ #undef HAVE_STRCASECMP - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR - -/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_CFTIME #undef HAVE_STRFTIME - -/* Define to 1 if you have the <strings.h> header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the <string.h> header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the <stropts.h> header file. */ -#undef HAVE_STROPTS_H - -/* Define to 1 if you have the <sys/param.h> header file. */ -#undef HAVE_SYS_PARAM_H - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the <sys/time.h> header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the <sys/types.h> header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ -#undef HAVE_SYS_WAIT_H - -/* Define to 1 if you have the `timelocal' function. */ +#undef HAVE_MEMCPY +#undef HAVE_MEMMOVE +#undef HAVE_LOCALTIME #undef HAVE_TIMELOCAL +#undef HAVE_STRCHR +#undef HAVE_SIGSETJMP +#undef HAVE_GETTIMEOFDAY +#undef HAVE_GET_PROCESS_STATS +#undef HAVE_SIGACTION +#undef HAVE_CRYPT +#undef HAVE_POLL -/* Define to 1 if you have the <time.h> header file. */ -#undef HAVE_TIME_H - -/* Define to 1 if you have the <unistd.h> header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if your compiler supports the volatile keyword */ +/* + * Define if your compiler supports the volatile keyword. + */ #undef HAVE_VOLATILE -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define to 1 if your environment supports SysV signals */ +/* + * Signal behaviour + */ #undef SYSV_SIGNALS -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to `int' if <sys/types.h> doesn't define. */ -#undef gid_t - -/* Define to `int' if <sys/types.h> does not define. */ -#undef mode_t - -/* Define to `int' if <sys/types.h> does not define. */ -#undef pid_t +/* + * sqsh-2.3 : Test availability of locale + */ +#undef HAVE_LOCALE_H +#undef HAVE_LOCALECONV +#undef HAVE_SETLOCALE -/* Define to `int' if <sys/types.h> doesn't define. */ -#undef uid_t +#endif diff --git a/src/config.h.nt b/src/config.h.nt deleted file mode 100644 index 47971d3..0000000 --- a/src/config.h.nt +++ /dev/null @@ -1,85 +0,0 @@ -/* config.h. Generated automatically by configure. */
-#ifndef config_h_included
-#define config_h_included
-
-/*
- * Define the following if you compiler is an ANSI compiler and supports
- * prototypes, etl a.
- */
-#define STDC_HEADERS 1
-
-/*
- * The include file sys/wait.h is required by sqsh_sigcld.c in order
- * to call wait_pid(). Define this if the header file is available.
- */
-#define HAVE_SYS_WAIT_H 1
-
-/*
- * Common header files.
- */
-#define HAVE_STDLIB_H 1 /* #include <stdlib.h> */
-#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> */
-#define HAVE_STRING_H 1 /* #include <string.h> */
-#define HAVE_FCNTL_H 1 /* #include <fcntl.h> */
-#define HAVE_UNISTD_H 1 /* #include <unistd.h> */
-#define HAVE_MEMORY_H 1 /* #include <memory.h> */
-#define HAVE_ERRNO_H 1 /* #include <errno.h> */
-#define HAVE_SYS_TIME_H 1 /* #include <sys/time.h> */
-#define HAVE_TIME_H 1 /* #include <time.h> */
-#define HAVE_SYS_PARAM_H 1 /* #include <sys/param.h> */
-#define HAVE_LIMITS_H 1 /* #include <limits.h> */
-/* #undef HAVE_CRYPT_H */ /* #include <crypt.h> */
-/* #undef HAVE_SHADOW_H */ /* #include <shadow.h> */
-/* #undef HAVE_STROPTS_H 1 */ /* #include <stropts.h> */
-
-/*
- * If you compiler doesn't fully support the keyword 'const'
- * then define const to be empty.
- */
-/* #undef const */
-
-/*
- * If the following types are not defined in stdlib.h and sys/types.h
- * then guess the closest possible data type.
- */
-/* #undef mode_t */
-/* #undef pid_t */
-/* #undef uid_t */
-
-/*
- * The following is the return type of a signal handler. On most
- * systems this is void.
- */
-#define RETSIGTYPE void
-
-/*
- * The following functions are frequently unavailable on certain
- * systems.
- */
-#define HAVE_STRCASECMP 1
-#define HAVE_STRERROR 1
-/* #undef HAVE_CFTIME */
-#define HAVE_STRFTIME 1
-#define HAVE_MEMCPY 1
-#define HAVE_MEMMOVE 1
-#define HAVE_LOCALTIME 1
-#define HAVE_TIMELOCAL 1
-#define HAVE_STRCHR 1
-#define HAVE_SIGSETJMP 1
-#define HAVE_GETTIMEOFDAY 1
-/* #undef HAVE_GET_PROCESS_STATS */
-#define HAVE_POSIX_SIGNALS 1
-/* #undef HAVE_CRYPT */
-/* #define HAVE_POLL 1 */
-
-/*
- * Define if your compiler supports the volatile keyword.
- */
-#define HAVE_VOLATILE 1
-
-/*
- * Signal behaviour
- */
-/* #undef SYSV_SIGNALS */
-
-#endif
@@ -31,7 +31,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp.c,v 1.3 2008/05/21 17:51:24 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp.c,v 1.6 2014/01/18 18:36:34 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -50,7 +50,7 @@ int g_dsp_interrupted = False; static CS_COMMAND *sg_cmd = NULL; /* - * g_dsp_props: This data structure contains the current set of + * g_dsp_props: This data structure contains the current set of * properties defined for the display sub-system. Be careful * when editing this data strcuture. */ @@ -178,6 +178,9 @@ int dsp_cmd( output, cmd, sql, flags ) sig_install( SIGINT, dsp_signal, (void*)NULL, 0 ); sig_install( SIGPIPE, dsp_signal, (void*)NULL, 0 ); + /* sqsh-2.5 - Feature p2f, reset g_p2fc before a new batch is started */ + g_p2fc = 0; + if (ct_send( cmd ) != CS_SUCCEED) ret = DSP_FAIL; @@ -188,7 +191,7 @@ int dsp_cmd( output, cmd, sql, flags ) * All that is left is to process the results of the current * query, reinstall the old signal handlers, and return! */ - if (ret == DSP_SUCCEED) + if (ret == DSP_SUCCEED) { if ((flags & DSP_F_NOTHING) != 0) { @@ -305,12 +308,26 @@ static int dsp_prop_set( prop, ptr, len ) { switch (prop) { + /* + * sqsh-2.1.9 - Introduced and remapped property types DSP_DATETIMEFMT, DSP_DATEFMT + * and DSP_TIMEFMT to implement date and time datatype conversions with strftime as + * already existed for the datetime and smalldatetime datatypes. + * This feature request was filed as bugreport 3603409 on Sourceforge. + */ + case DSP_DATETIMEFMT: + return dsp_datetimefmt_set( (char*)ptr ); + break; + case DSP_DATEFMT: return dsp_datefmt_set( (char*)ptr ); break; + case DSP_TIMEFMT: + return dsp_timefmt_set( (char*)ptr ); + break; + case DSP_COLWIDTH: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_COLWDTH, %d)\n", *((int*)ptr));) if (*((int*)ptr) < 1) @@ -323,7 +340,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_FLOAT_PREC: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_FLOAT_PREC, %d)\n", *((int*)ptr));) if (*((int*)ptr) < 0 || *((int*)ptr) < g_dsp_props.p_flt_scale) @@ -336,7 +353,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_FLOAT_SCALE: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_FLOAT_SCALE, %d)\n", *((int*)ptr));) @@ -350,7 +367,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_REAL_PREC: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_REAL_PREC, %d)\n", *((int*)ptr));) if (*((int*)ptr) < 0 || *((int*)ptr) < g_dsp_props.p_real_scale) @@ -363,7 +380,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_REAL_SCALE: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_REAL_SCALE, %d)\n", *((int*)ptr));) @@ -377,7 +394,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_STYLE: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_STYLE, %d)\n", *((int*)ptr));) if (!(DSP_VALID_STYLE( *((int*)ptr) ))) @@ -389,8 +406,8 @@ static int dsp_prop_set( prop, ptr, len ) g_dsp_props.p_style = *((int*)ptr); break; - case DSP_WIDTH: - DBG(sqsh_debug(DEBUG_DISPLAY, + case DSP_WIDTH: + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_WIDTH, %d)\n", *((int*)ptr));) if (*((int*)ptr) >= 30) @@ -404,8 +421,8 @@ static int dsp_prop_set( prop, ptr, len ) } break; - case DSP_OUTPUTPARMS: - DBG(sqsh_debug(DEBUG_DISPLAY, + case DSP_OUTPUTPARMS: + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_OUTPUTPARMS, %d)\n", *((int*)ptr));) @@ -421,10 +438,13 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_COLSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_COLSEP, '%s')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_COLSEP, '%s')\n", (ptr == NULL)?"NULL":((char*)ptr));) + if (ptr == NULL || strcasecmp (ptr, "default") == 0) + ptr = " "; /* sqsh-2.5 - Set to default when ptr is NULL */ + if (len == DSP_NULLTERM) { len = strlen( (char*)ptr ); @@ -432,7 +452,7 @@ static int dsp_prop_set( prop, ptr, len ) if (len > MAX_SEPLEN || len < 0) { - sqsh_set_error( SQSH_E_INVAL, + sqsh_set_error( SQSH_E_INVAL, "Invalid length of column separator (between 0 and %d allowed)", MAX_SEPLEN ); return DSP_FAIL; @@ -446,10 +466,13 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_BCP_COLSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_COLSEP, '%s')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_COLSEP, '%s')\n", (ptr == NULL)?"NULL":((char*)ptr));) + if (ptr == NULL || strcasecmp (ptr, "default") == 0) + ptr = "|"; /* sqsh-2.5 - Set to default when ptr is NULL */ + if (len == DSP_NULLTERM) { len = strlen( (char*)ptr ); @@ -457,7 +480,7 @@ static int dsp_prop_set( prop, ptr, len ) if (len > MAX_SEPLEN || len < 0) { - sqsh_set_error( SQSH_E_INVAL, + sqsh_set_error( SQSH_E_INVAL, "Invalid length of bcp col separator (between 0 and %d allowed)", MAX_SEPLEN ); return DSP_FAIL; @@ -471,10 +494,13 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_BCP_ROWSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_ROWSEP, '%s')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_ROWSEP, '%s')\n", (ptr == NULL)?"NULL":((char*)ptr));) + if (ptr == NULL || strcasecmp (ptr, "default") == 0) + ptr = "|"; /* sqsh-2.5 - Set to default when ptr is NULL */ + if (len == DSP_NULLTERM) { len = strlen( (char*)ptr ); @@ -482,7 +508,7 @@ static int dsp_prop_set( prop, ptr, len ) if (len > MAX_SEPLEN || len < 0) { - sqsh_set_error( SQSH_E_INVAL, + sqsh_set_error( SQSH_E_INVAL, "Invalid length of bcp row separator (between 0 and %d allowed)", MAX_SEPLEN ); return DSP_FAIL; @@ -496,8 +522,8 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_BCP_TRIM: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_TRIM, '%d')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_BCP_TRIM, '%d')\n", (ptr == NULL)?-1:*((int*)ptr));) if (*((int*)ptr) == 0) @@ -511,10 +537,13 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_LINESEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_LINESEP, '%s')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_LINESEP, '%s')\n", (ptr == NULL)?"NULL":((char*)ptr));) + if (ptr == NULL || strcasecmp (ptr, "default") == 0) + ptr = "\n\t"; /* sqsh-2.5 - Set to default when ptr is NULL */ + if (len == DSP_NULLTERM) { len = strlen( (char*)ptr ); @@ -522,7 +551,7 @@ static int dsp_prop_set( prop, ptr, len ) if (len > MAX_SEPLEN || len < 0) { - sqsh_set_error( SQSH_E_INVAL, + sqsh_set_error( SQSH_E_INVAL, "Invalid length of line separator (between 0 and %d allowed)", MAX_SEPLEN ); return DSP_FAIL; @@ -535,8 +564,8 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_XGEOM: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_SET, DSP_XGEOM, '%s')\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_SET, DSP_XGEOM, '%s')\n", (ptr == NULL)?"NULL":((char*)ptr));) if (len == DSP_NULLTERM) @@ -546,7 +575,7 @@ static int dsp_prop_set( prop, ptr, len ) if (len > MAX_XGEOM || len < 0) { - sqsh_set_error( SQSH_E_INVAL, + sqsh_set_error( SQSH_E_INVAL, "Invalid length of X geometry (between 0 and %d allowed)", MAX_XGEOM ); return DSP_FAIL; @@ -557,7 +586,7 @@ static int dsp_prop_set( prop, ptr, len ) break; case DSP_MAXLEN: - DBG(sqsh_debug(DEBUG_DISPLAY, + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_prop: dsp_prop(DSP_SET, DSP_MAXLEN, %d)\n", *((int*)ptr));) if (*((int*)ptr) < 0) @@ -591,49 +620,69 @@ static int dsp_prop_get( prop, ptr, len ) { switch (prop) { + /* + * sqsh-2.1.9 - Introduced and remapped property types DSP_DATETIMEFMT, DSP_DATEFMT + * and DSP_TIMEFMT to implement date and time datatype conversions with strftime as + * already existed for the datetime and smalldatetime datatypes. + * This feature request was filed as bugreport 3603409 on Sourceforge. + */ case DSP_COLWIDTH: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_COLWIDTH) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_COLWIDTH) = %d\n", g_dsp_props.p_colwidth);) *((int*)ptr) = g_dsp_props.p_colwidth; break; case DSP_FLOAT_PREC: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_FLOAT_PREC) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_FLOAT_PREC) = %d\n", g_dsp_props.p_flt_prec);) *((int*)ptr) = g_dsp_props.p_flt_prec; break; case DSP_FLOAT_SCALE: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_FLOAT_SCALE) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_FLOAT_SCALE) = %d\n", g_dsp_props.p_flt_scale);) *((int*)ptr) = g_dsp_props.p_flt_scale; break; case DSP_REAL_PREC: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_REAL_PREC) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_REAL_PREC) = %d\n", g_dsp_props.p_real_prec);) *((int*)ptr) = g_dsp_props.p_real_prec; break; case DSP_REAL_SCALE: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_REAL_SCALE) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_REAL_SCALE) = %d\n", g_dsp_props.p_real_scale);) *((int*)ptr) = g_dsp_props.p_real_scale; break; + case DSP_DATETIMEFMT: + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_DATETIMEFMT) = %s\n", + dsp_datetimefmt_get());) + + if (len <= 0) + { + sqsh_set_error( SQSH_E_INVAL, "length must be greater than 0" ); + return DSP_FAIL; + } + + strncpy( (char*)ptr, dsp_datetimefmt_get(), len ); + break; + case DSP_DATEFMT: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_DATEFMT) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_DATEFMT) = %s\n", dsp_datefmt_get());) if (len <= 0) @@ -644,74 +693,88 @@ static int dsp_prop_get( prop, ptr, len ) strncpy( (char*)ptr, dsp_datefmt_get(), len ); break; + + case DSP_TIMEFMT: + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_TIMEFMT) = %s\n", + dsp_timefmt_get());) + + if (len <= 0) + { + sqsh_set_error( SQSH_E_INVAL, "length must be greater than 0" ); + return DSP_FAIL; + } + + strncpy( (char*)ptr, dsp_timefmt_get(), len ); + break; case DSP_STYLE: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_STYLE) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_STYLE) = %d\n", g_dsp_props.p_style);) *((int*)ptr) = g_dsp_props.p_style; break; - case DSP_WIDTH: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_WIDTH) = %d\n", + case DSP_WIDTH: + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_WIDTH) = %d\n", g_dsp_props.p_width);) *((int*)ptr) = g_dsp_props.p_width; break; - case DSP_OUTPUTPARMS: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_OUTPUTPARMS) = %d\n", + case DSP_OUTPUTPARMS: + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_OUTPUTPARMS) = %d\n", g_dsp_props.p_outputparms);) *((int*)ptr) = g_dsp_props.p_outputparms; break; case DSP_COLSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_COLSEP) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_COLSEP) = %s\n", g_dsp_props.p_colsep);) strncpy( (char*)ptr, g_dsp_props.p_colsep, len ); break; case DSP_BCP_COLSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_COLSEP) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_COLSEP) = %s\n", g_dsp_props.p_bcp_colsep);) strncpy( (char*)ptr, g_dsp_props.p_bcp_colsep, len ); break; case DSP_BCP_ROWSEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_ROWSEP) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_ROWSEP) = %s\n", g_dsp_props.p_bcp_rowsep);) strncpy( (char*)ptr, g_dsp_props.p_bcp_rowsep, len ); break; case DSP_BCP_TRIM: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_TRIM) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_BCP_TRIM) = %d\n", g_dsp_props.p_bcp_trim);) *((int*)ptr) = g_dsp_props.p_bcp_trim; break; case DSP_LINESEP: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_LINESEP) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_LINESEP) = %s\n", g_dsp_props.p_linesep);) strncpy( (char*)ptr, g_dsp_props.p_linesep, len ); break; case DSP_XGEOM: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_XGEOM) = %s\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_XGEOM) = %s\n", g_dsp_props.p_xgeom);) if (len <= 0) @@ -724,8 +787,8 @@ static int dsp_prop_get( prop, ptr, len ) break; case DSP_MAXLEN: - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_prop: dsp_prop(DSP_GET, DSP_MAXLEN) = %d\n", + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_prop: dsp_prop(DSP_GET, DSP_MAXLEN) = %d\n", g_dsp_props.p_maxlen);) *((int*)ptr) = g_dsp_props.p_maxlen; @@ -107,6 +107,7 @@ typedef struct _dsp_desc_t { */ #define DSP_F_NOHEADERS (1<<0) /* Suppress headers */ #define DSP_F_NOFOOTERS (1<<1) /* Suppress footers */ +#define DSP_F_NOSEPLINE (1<<2) /* Suppress seperator lines */ #define DSP_F_NOTHING (1<<3) /* Everything */ #define DSP_F_X (1<<4) /* Send output to X Window */ @@ -122,13 +123,17 @@ extern int g_dsp_interrupted; #define DSP_GET 1 #define DSP_SET 2 +/* + * sqsh-2.1.9 - Introduced or changed property types DSP_DATETIMEFMT, DSP_DATEFMT and DSP_TIMEFMT + */ + /*-- Types of properties for dsp_prop() --*/ #define DSP_WIDTH 1 #define DSP_COLSEP 2 #define DSP_LINESEP 3 #define DSP_XGEOM 4 #define DSP_STYLE 5 -#define DSP_DATEFMT 6 +#define DSP_DATETIMEFMT 6 #define DSP_FLOAT_SCALE 7 #define DSP_FLOAT_PREC 8 #define DSP_REAL_SCALE 9 @@ -141,7 +146,9 @@ extern int g_dsp_interrupted; #define DSP_MAXLEN 16 #define DSP_CSV_COLSEP 17 #define DSP_CSV_ROWSEP 18 -#define DSP_VALID_PROP(p) ((p) >= DSP_WIDTH && (p) <= DSP_CSV_ROWSEP) +#define DSP_DATEFMT 19 +#define DSP_TIMEFMT 20 +#define DSP_VALID_PROP(p) ((p) >= DSP_WIDTH && (p) <= DSP_TIMEFMT) /*-- Length for dsp_prop() --*/ @@ -226,34 +233,44 @@ typedef struct dsp_prop_st { * (or as defaulted). */ extern dsp_prop_t g_dsp_props; - + +/* + * sqsh-2.1.9 - To implement the date and time datatypes conversion feature, + * the following prototypes have been added or modified: dsp_datetimefmt_set, + * dsp_datetimefmt_get, dsp_datefmt_set, dsp_datefmt_get, dsp_timefmt_set, + * dsp_timefmt_get and dsp_datetime_conv. +*/ + /*-- Internal Prototypes --*/ -dsp_out_t* dsp_fopen _ANSI_ARGS(( FILE* )); -int dsp_fputc _ANSI_ARGS(( int, dsp_out_t* )); -int dsp_fputs _ANSI_ARGS(( char*, dsp_out_t* )); -int dsp_fflush _ANSI_ARGS(( dsp_out_t* )); -int dsp_fprintf _ANSI_ARGS(( dsp_out_t*, char*, ... )); -int dsp_fclose _ANSI_ARGS(( dsp_out_t* )); -int dsp_horiz _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_meta _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_vert _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_bcp _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_csv _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_html _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_none _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_pretty _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); -int dsp_x _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int, dsp_t* )); -int dsp_datefmt_set _ANSI_ARGS(( char* )); -char* dsp_datefmt_get _ANSI_ARGS(( void )); -dsp_desc_t* dsp_desc_bind _ANSI_ARGS(( CS_COMMAND*, CS_INT )); -CS_INT dsp_desc_fetch _ANSI_ARGS(( CS_COMMAND*, dsp_desc_t* )); -void dsp_desc_destroy _ANSI_ARGS(( dsp_desc_t* )); -CS_INT dsp_datetime_len _ANSI_ARGS(( CS_CONTEXT*, CS_INT )); -CS_INT dsp_datetime4_len _ANSI_ARGS(( CS_CONTEXT* )); -CS_INT dsp_money_len _ANSI_ARGS(( CS_CONTEXT* )); -CS_INT dsp_money4_len _ANSI_ARGS(( CS_CONTEXT* )); -CS_RETCODE dsp_datetime_conv _ANSI_ARGS(( CS_CONTEXT*, CS_DATAFMT*, CS_VOID*, - CS_CHAR*, CS_INT )); +dsp_out_t* dsp_fopen _ANSI_ARGS(( FILE* )); +int dsp_fputc _ANSI_ARGS(( int, dsp_out_t* )); +int dsp_fputs _ANSI_ARGS(( char*, dsp_out_t* )); +int dsp_fflush _ANSI_ARGS(( dsp_out_t* )); +int dsp_fprintf _ANSI_ARGS(( dsp_out_t*, char*, ... )); +int dsp_fclose _ANSI_ARGS(( dsp_out_t* )); +int dsp_horiz _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_meta _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_vert _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_bcp _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_csv _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_html _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_none _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_pretty _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int )); +int dsp_x _ANSI_ARGS(( dsp_out_t*, CS_COMMAND*, int, dsp_t* )); +int dsp_datetimefmt_set _ANSI_ARGS(( char* )); +char* dsp_datetimefmt_get _ANSI_ARGS(( void )); +int dsp_datefmt_set _ANSI_ARGS(( char* )); +char* dsp_datefmt_get _ANSI_ARGS(( void )); +int dsp_timefmt_set _ANSI_ARGS(( char* )); +char* dsp_timefmt_get _ANSI_ARGS(( void )); +dsp_desc_t* dsp_desc_bind _ANSI_ARGS(( CS_COMMAND*, CS_INT )); +CS_INT dsp_desc_fetch _ANSI_ARGS(( CS_COMMAND*, dsp_desc_t* )); +void dsp_desc_destroy _ANSI_ARGS(( dsp_desc_t* )); +CS_INT dsp_datetime_len _ANSI_ARGS(( CS_CONTEXT*, CS_INT )); +CS_INT dsp_datetime4_len _ANSI_ARGS(( CS_CONTEXT* )); +CS_INT dsp_money_len _ANSI_ARGS(( CS_CONTEXT* )); +CS_INT dsp_money4_len _ANSI_ARGS(( CS_CONTEXT* )); +CS_RETCODE dsp_datetime_conv _ANSI_ARGS(( CS_CONTEXT*, CS_DATAFMT*, CS_VOID*, CS_CHAR*, CS_INT, CS_INT )); #if defined(DEBUG) char* dsp_result_name _ANSI_ARGS(( CS_INT )); diff --git a/src/dsp_conv.c b/src/dsp_conv.c index 78e1027..6c6878c 100644 --- a/src/dsp_conv.c +++ b/src/dsp_conv.c @@ -28,34 +28,59 @@ #include "sqsh_error.h" #include "sqsh_compat.h" #include "dsp.h" +#include "config.h" + +#if defined(HAVE_LOCALE_H) +#include <locale.h> +#endif /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_conv.c,v 1.2 2004/04/10 00:10:30 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_conv.c,v 1.7 2013/07/23 20:57:28 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ +/* + * sqsh-2.1.9 - Introduced and remapped global variables sg_datetime_fmt, sg_date_fmt + * and sg_time_fmt as well as the functions dsp_datetimefmt_set, dsp_datetimefmt_get, + * dsp_datefmt_set, dsp_datefmt_get, dsp_timefmt_set and dsp_timefmt_get to implement + * date and time datatype conversions with strftime as already existed for the datetime + * and smalldatetime datatypes. + * This feature request was filed as bugreport 3603409 on Sourceforge. + */ + /*-- Local Globals --*/ static char sg_datetime_fmt[64] = "\0"; +static char sg_date_fmt[64] = "\0"; +static char sg_time_fmt[64] = "\0"; static int sg_datetime_len = -1; static int sg_datetime4_len = -1; static int sg_date_len = -1; static int sg_time_len = -1; +static int sg_bigdatetime_len = -1; +static int sg_bigtime_len = -1; +#if defined(HAVE_SETLOCALE) +static char *sg_locale = NULL; +#endif +#if defined(CS_BIGDATETIME_TYPE) && defined(CS_BIGTIME_TYPE) +static char sg_datetime_def[64] = "%b %d %Y %l:%M:%S.%q%p"; +static char sg_time_def[64] = "%l:%M:%S.%q%p"; +#endif /*-- Prototypes --*/ -static CS_INT dsp_type_len _ANSI_ARGS(( CS_CONTEXT*, CS_CHAR*, +static CS_INT dsp_type_len _ANSI_ARGS(( CS_CONTEXT*, CS_CHAR*, CS_DATAFMT*, CS_VOID* )); static char* dsp_datetime_strip _ANSI_ARGS(( CS_INT, char*, int )); /* - * dsp_datefmt_set(): + * dsp_datetimefmt_set(): * * Set the conversion format to be used by the display routine when * converting dates. A format string of NULL or "default" indicates * that the default CT-Lib conversion method should be used. Otherwise * a string suitable for use by strftime() should be supplied. */ -int dsp_datefmt_set( fmt ) +int dsp_datetimefmt_set( fmt ) char *fmt; { /* @@ -64,8 +89,9 @@ int dsp_datefmt_set( fmt ) * we are now changing the format from what it was, these * variables should be reset. */ - sg_datetime_len = -1; - sg_datetime4_len = -1; + sg_datetime_len = -1; + sg_datetime4_len = -1; + sg_bigdatetime_len = -1; /* * If the format is NULL or "default", then we simply store @@ -82,18 +108,19 @@ int dsp_datefmt_set( fmt ) * longer than the size of sg_datetime_fmt, then we quietly * trim it to the appropriate length. */ - strncpy( sg_datetime_fmt, fmt, sizeof(sg_datetime_fmt) ); + strncpy( sg_datetime_fmt, fmt, sizeof(sg_datetime_fmt)-1 ); + sg_datetime_fmt[sizeof(sg_datetime_fmt)-1] = '\0'; return DSP_SUCCEED; } /* - * dsp_datefmt_get(): + * dsp_datetimefmt_get(): * * Retrieve the conversion format to be used by the display routine when * converting dates. A format string of NULL or "default" indicates * that the default CT-Lib conversion method should be used. */ -char* dsp_datefmt_get() +char* dsp_datetimefmt_get() { if (*sg_datetime_fmt == '\0') { @@ -103,14 +130,139 @@ char* dsp_datefmt_get() return sg_datetime_fmt; } + +/* + * dsp_datefmt_set(): + * + * sqsh-2.1.9 - Date and time datatype conversion feature. + * + * Set the conversion format to be used by the display routine when + * converting dates. A format string of NULL or "default" indicates + * that the default CT-Lib conversion method should be used. Otherwise + * a string suitable for use by strftime() should be supplied. + */ +int dsp_datefmt_set( fmt ) + char *fmt; +{ + /* + * The dsp_datetime_len() function uses these global variables + * to store the results of the last time it was called. Since + * we are now changing the format from what it was, these + * variables should be reset. + */ + sg_date_len = -1; + + /* + * If the format is NULL or "default", then we simply store + * away the format to be used as an empty string. + */ + if (fmt == NULL || strcmp( fmt, "default" ) == 0) + { + sg_date_fmt[0] = '\0'; + return DSP_SUCCEED; + } + + /* + * This is a little cheesy. If the user passes us a string + * longer than the size of sg_date_fmt, then we quietly + * trim it to the appropriate length. + */ + strncpy( sg_date_fmt, fmt, sizeof(sg_date_fmt)-1 ); + sg_date_fmt[sizeof(sg_date_fmt)-1] = '\0'; + return DSP_SUCCEED; +} + +/* + * dsp_datefmt_get(): + * + * sqsh-2.1.9 - Date and time datatype conversion feature. + * + * Retrieve the conversion format to be used by the display routine when + * converting dates. A format string of NULL or "default" indicates + * that the default CT-Lib conversion method should be used. + */ +char* dsp_datefmt_get() +{ + if (*sg_date_fmt == '\0') + { + return "default"; + } + + return sg_date_fmt; +} + +/* + * dsp_timefmt_set(): + * + * sqsh-2.1.9 - Date and time datatype conversion feature. + * + * Set the conversion format to be used by the display routine when + * converting times. A format string of NULL or "default" indicates + * that the default CT-Lib conversion method should be used. Otherwise + * a string suitable for use by strftime() should be supplied. + */ +int dsp_timefmt_set( fmt ) + char *fmt; +{ + /* + * The dsp_time_len() function uses these global variables + * to store the results of the last time it was called. Since + * we are now changing the format from what it was, these + * variables should be reset. + */ + sg_time_len = -1; + sg_bigtime_len = -1; + + /* + * If the format is NULL or "default", then we simply store + * away the format to be used as an empty string. + */ + if (fmt == NULL || strcmp( fmt, "default" ) == 0) + { + sg_time_fmt[0] = '\0'; + return DSP_SUCCEED; + } + + /* + * This is a little cheesy. If the user passes us a string + * longer than the size of sg_time_fmt, then we quietly + * trim it to the appropriate length. + */ + strncpy( sg_time_fmt, fmt, sizeof(sg_time_fmt)-1 ); + sg_time_fmt[sizeof(sg_time_fmt)-1] = '\0'; + return DSP_SUCCEED; +} + +/* + * dsp_timefmt_get(): + * + * sqsh-2.1.9 - Date and time datatype conversion feature. + * + * Retrieve the conversion format to be used by the display routine when + * converting dates. A format string of NULL or "default" indicates + * that the default CT-Lib conversion method should be used. + */ +char* dsp_timefmt_get() +{ + if (*sg_time_fmt == '\0') + { + return "default"; + } + + return sg_time_fmt; +} + /* * dsp_datetime_len(): * * Calculates the maximum number of characters required to store * a date in a string format of the current locale. This function - * is similar to dsp_money_len() except that every month is + * is similar to dsp_money_len() except that every month is * converted to verify if particular month names are longer than * others. + * + * sqsh-2.1.9 - Also implement date and time datatype conversions. + * sqsh-2.3 - Improve handling of bigdatetime and bigtime data types. */ CS_INT dsp_datetime_len( ctxt, type ) CS_CONTEXT *ctxt; @@ -125,6 +277,30 @@ CS_INT dsp_datetime_len( ctxt, type ) int max_len; int len; char *fmt; +#if defined(CS_BIGDATETIME_TYPE) && defined(CS_BIGTIME_TYPE) + char *conv_fmt; +#endif +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) + char *locale; + + /* + * sqsh-2.3 : If the locale was changed recently, we have to reset + * the cached type len values. + */ + locale = setlocale (LC_ALL, NULL); + if ( sg_locale != locale ) + { + DBG(sqsh_debug(DEBUG_DISPLAY, "locale changed to %s\n", locale);) + + sg_locale = locale; + sg_datetime_len = -1; + sg_datetime4_len = -1; + sg_date_len = -1; + sg_time_len = -1; + sg_bigdatetime_len = -1; + sg_bigtime_len = -1; + } +#endif /* * Check to see if we have cached the value from the last time @@ -155,6 +331,20 @@ CS_INT dsp_datetime_len( ctxt, type ) } #endif +#if defined(CS_BIGDATETIME_TYPE) + if (type == CS_BIGDATETIME_TYPE && sg_bigdatetime_len != -1) + { + return sg_bigdatetime_len; + } +#endif + +#if defined(CS_BIGTIME_TYPE) + if (type == CS_BIGTIME_TYPE && sg_bigtime_len != -1) + { + return sg_bigtime_len; + } +#endif + /* * If the user is using the default CT-Lib conversion format then * we try a brute force test of all of the months in the year, @@ -162,15 +352,12 @@ CS_INT dsp_datetime_len( ctxt, type ) */ max_len = 0; - /* The user defined conversion with strftime, etc. is not implemented - for the CS_DATE_TYPE and CS_TIME_TYPE datatypes */ - if (*sg_datetime_fmt == '\0' || + if ((type == CS_DATETIME_TYPE && *sg_datetime_fmt == '\0') + || (type == CS_DATETIME4_TYPE && *sg_datetime_fmt == '\0') #if defined(CS_DATE_TYPE) - (type == CS_DATE_TYPE || type == CS_TIME_TYPE) -#else - 0 + || (type == CS_DATE_TYPE && *sg_date_fmt == '\0') #endif - ) + ) { dt_fmt.datatype = type; dt_fmt.maxlength = sizeof(CS_DATETIME); @@ -189,21 +376,52 @@ CS_INT dsp_datetime_len( ctxt, type ) for (i = 1; i <= 12; i++) { /*-- Build a made-up day of the month --*/ - sprintf( dt_buf, "%d/12/1997 11:59:53:123PM", i ); + switch (type) + { + case CS_DATETIME_TYPE: + sprintf( dt_buf, "%d/12/1997 11:59:53.123PM", i ); + break; + case CS_DATETIME4_TYPE: + sprintf( dt_buf, "%d/12/1997 11:59PM", i ); + break; +#if defined(CS_DATE_TYPE) + case CS_DATE_TYPE: + sprintf( dt_buf, "%d/12/1997", i ); + break; +#endif + default: + sprintf( dt_buf, "%d/12/1997 11:59:53PM", i ); + break; + } len = dsp_type_len( ctxt, (CS_CHAR*)dt_buf, &dt_fmt, &dt ); /*-- Keep track of the longest date encountered --*/ max_len = max(len, max_len); } } +#if defined(CS_TIME_TYPE) + else if (type == CS_TIME_TYPE && *sg_time_fmt == '\0') + { + dt_fmt.datatype = type; + dt_fmt.maxlength = sizeof(CS_DATETIME); + dt_fmt.locale = NULL; + dt_fmt.format = CS_FMT_UNUSED; + dt_fmt.scale = 0; + dt_fmt.precision = 0; + sprintf( dt_buf, "11:59:53.123PM" ); + max_len = dsp_type_len( ctxt, (CS_CHAR*)dt_buf, &dt_fmt, &dt ); + } +#endif else { /* * If the user has supplied a display format to be used in * place of the CT-Lib format, then we have a lot of work - * to do; beginning wth building a reasonable UNIX time + * to do; beginning with building a reasonable UNIX time * structure. + * sqsh-2.3 : Note that CS_BIGDATETIME_TYPE and CS_BIGTIME_TYPE + * will use a default format here, if one is not supplied. */ tm.tm_sec = 59; tm.tm_min = 59; @@ -216,10 +434,37 @@ CS_INT dsp_datetime_len( ctxt, type ) /* * Strip down the format string as defined by the CS_DATETIME - * datatype, and replace the ms (%u) with the longest possible + * datatype, and replace the ms (%q) with the longest possible * number. */ - fmt = dsp_datetime_strip( type, sg_datetime_fmt, 999 ); + switch (type) + { +#if defined(CS_DATE_TYPE) + case CS_DATE_TYPE: + fmt = dsp_datetime_strip( type, sg_date_fmt, 999 ); + break; +#endif +#if defined(CS_TIME_TYPE) + case CS_TIME_TYPE: + fmt = dsp_datetime_strip( type, sg_time_fmt, 999 ); + break; +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: + conv_fmt = sg_datetime_fmt[0] == '\0' ? sg_datetime_def : sg_datetime_fmt; + fmt = dsp_datetime_strip( type, conv_fmt, 999999 ); + break; +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: + conv_fmt = sg_time_fmt[0] == '\0' ? sg_time_def : sg_time_fmt; + fmt = dsp_datetime_strip( type, conv_fmt, 999999 ); + break; +#endif + default: + fmt = dsp_datetime_strip( type, sg_datetime_fmt, 999 ); + break; + } max_len = 0; max_month = 0; @@ -270,31 +515,42 @@ CS_INT dsp_datetime_len( ctxt, type ) } } - DBG(sqsh_debug(DEBUG_DISPLAY, - "dsp_datetime_len: %s = %d chars\n", - (type == CS_DATETIME_TYPE)?"CS_DATETIME":"CS_SMALLDATETIME", - max_len);) - - switch(type) { - case CS_DATETIME_TYPE: - sg_datetime_len = max_len; - break; - case CS_DATETIME4_TYPE: - sg_datetime4_len = max_len; - break; + DBG(sqsh_debug(DEBUG_DISPLAY, + "dsp_datetime_len: %s (type %d) = %d chars\n", + (type == CS_DATETIME_TYPE)?"CS_DATETIME":"Other DATE/TIME type", + type, max_len);) + + switch (type) { + case CS_DATETIME_TYPE: + sg_datetime_len = max_len; + break; + + case CS_DATETIME4_TYPE: + sg_datetime4_len = max_len; + break; #if defined(CS_DATE_TYPE) - case CS_DATE_TYPE: - sg_date_len = max_len; - break; + case CS_DATE_TYPE: + sg_date_len = max_len; + break; #endif #if defined(CS_TIME_TYPE) - case CS_TIME_TYPE: - sg_time_len = max_len; - break; + case CS_TIME_TYPE: + sg_time_len = max_len; + break; +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: + sg_bigdatetime_len = max_len; + break; +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: + sg_bigtime_len = max_len; + break; #endif } -/* fprintf(stderr, "type = %d, len = %d\n", type, max_len); */ +/* fprintf(stderr, "type = %d, len = %d\n", type, max_len); */ return (CS_INT)max_len; } @@ -306,30 +562,56 @@ CS_INT dsp_datetime_len( ctxt, type ) * of length, len according to the conversion style as defined in * dsp_datetime_fmt(). This function returns CS_SUCCEED up success or * CS_FAIL upon failure (duh!). + * + * sqsh-2.1.9 - Also implement the date and time datatype conversions. */ -CS_RETCODE dsp_datetime_conv( ctx, dt_fmt, dt, buf, len ) +CS_RETCODE dsp_datetime_conv( ctx, dt_fmt, dt, buf, len, type ) CS_CONTEXT *ctx; /* Context */ CS_DATAFMT *dt_fmt; /* Date format */ CS_VOID *dt; /* Pointer to date */ CS_CHAR *buf; /* Buffer */ CS_INT len; /* Length */ + CS_INT type; /* CS_TYPE */ { struct tm tm; char *fmt; CS_DATEREC dr; CS_DATAFMT cs_fmt; + char *conv_fmt; + + + switch (type) + { +#if defined(CS_DATE_TYPE) + case CS_DATE_TYPE: + conv_fmt = sg_date_fmt; + break; +#endif +#if defined(CS_TIME_TYPE) + case CS_TIME_TYPE: + conv_fmt = sg_time_fmt; + break; +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: + conv_fmt = sg_datetime_fmt[0] == '\0' ? sg_datetime_def : sg_datetime_fmt; + break; +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: + conv_fmt = sg_time_fmt[0] == '\0' ? sg_time_def : sg_time_fmt; + break; +#endif + default: + conv_fmt = sg_datetime_fmt; + break; + } /* * If the user has not specified a format, then we let ct-lib * do its thing. This seems to be OK for most platforms. */ - if (*sg_datetime_fmt == '\0' || -#if defined(CS_DATE_TYPE) - (dt_fmt->datatype == CS_DATE_TYPE || dt_fmt->datatype == CS_TIME_TYPE) -#else - 0 -#endif - ) + if (*conv_fmt == '\0') { cs_fmt.datatype = CS_CHAR_TYPE; cs_fmt.locale = NULL; @@ -345,8 +627,7 @@ CS_RETCODE dsp_datetime_conv( ctx, dt_fmt, dt, buf, len ) (CS_VOID*)buf, /* String */ (CS_INT*)NULL ) != CS_SUCCEED) { - fprintf( stderr, - "dsp_datetime_conv: cs_convert(DATETIME->CHAR) failed\n" ); + fprintf( stderr, "dsp_datetime_conv: cs_convert(DATETIME->CHAR) failed\n" ); return CS_FAIL; } @@ -379,8 +660,12 @@ CS_RETCODE dsp_datetime_conv( ctx, dt_fmt, dt, buf, len ) * type of date that we are processing and replace the ms * field if it exists. */ - fmt = dsp_datetime_strip( dt_fmt->datatype, sg_datetime_fmt, - (int)dr.datemsecond ); +#if defined(CS_BIGDATETIME_TYPE) && defined(CS_BIGTIME_TYPE) + if (dt_fmt->datatype == CS_BIGDATETIME_TYPE || dt_fmt->datatype == CS_BIGTIME_TYPE) + fmt = dsp_datetime_strip( dt_fmt->datatype, conv_fmt, (int) dr.datesecfrac ); + else +#endif + fmt = dsp_datetime_strip( dt_fmt->datatype, conv_fmt, (int) dr.datemsecond ); /* * According to the strftime(3C) documentation, there is no real @@ -426,12 +711,12 @@ CS_INT dsp_money_len( ctxt ) */ len = dsp_type_len( ctxt, (CS_CHAR*)"-922337203685477.5808", &mon_fmt, (CS_VOID*)&mon ); - + if (len < 19) { len = 19; } - + DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_money_len: CS_MONEY = %d chars\n", len);) @@ -550,7 +835,7 @@ static char* dsp_datetime_strip( type, fmt, ms ) /* * Now, we want to keep date format that the caller specified, - * but we want to strip out the milisecond (%u) and the + * but we want to strip out the millisecond (%q) and the * delimeter for small and regular datetimes ([]). */ for (cp = new_fmt; *fmt != '\0'; ++fmt) @@ -558,11 +843,21 @@ static char* dsp_datetime_strip( type, fmt, ms ) switch (*fmt) { case '%': - if (*(fmt + 1) == 'u') + if (*(fmt + 1) == 'q') { - fmt += 2; - sprintf( cp, "%03d", ms ); - cp += 3; + fmt += 1; +#if defined(CS_BIGDATETIME_TYPE) && defined(CS_BIGTIME_TYPE) + if (type == CS_BIGDATETIME_TYPE || type == CS_BIGTIME_TYPE) + { + sprintf( cp, "%06d", ms ); + cp += 6; + } + else +#endif + { + sprintf( cp, "%03d", ms ); + cp += 3; + } } else { @@ -583,7 +878,7 @@ static char* dsp_datetime_strip( type, fmt, ms ) case ']': break; - + default: *cp++ = *fmt; } diff --git a/src/dsp_csv.c b/src/dsp_csv.c index 75f889e..32b1c58 100644 --- a/src/dsp_csv.c +++ b/src/dsp_csv.c @@ -34,7 +34,7 @@ extern int errno; /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_csv.c,v 1.1 2005/07/24 11:41:19 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_csv.c,v 1.2 2013/02/19 18:06:42 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -206,7 +206,12 @@ static void dsp_col( output, col_value, col_width ) if (end > col_value || (end == col_value && !isspace((int)*end))) { dsp_fputc('"', output); for (; col_value <= end; ++col_value) + { + /* sqsh-2.1.9 - Bug fix 3525302 */ + if (*col_value == '"') + dsp_fputc('"', output); dsp_fputc( *col_value, output ); + } dsp_fputc('"', output); } } diff --git a/src/dsp_desc.c b/src/dsp_desc.c index 3bb968f..f2bbd54 100644 --- a/src/dsp_desc.c +++ b/src/dsp_desc.c @@ -32,10 +32,19 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_desc.c,v 1.6 2010/05/03 19:52:09 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_desc.c,v 1.13 2013/12/03 09:22:23 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ +/* + * sqsh-2.5 : FreeTDS defines a datatype CS_UNIQUE_TYPE for the MSSQL uniqueidentifier. + * In order to compile correctly and make coding somewhat easier we define the type here, + * in case it was not defined already. +*/ +#if !defined(CS_UNIQUE_TYPE) +#define CS_UNIQUE_TYPE 40 +#endif + /*-- Local Prototypes --*/ static CS_INT dsp_dlen _ANSI_ARGS(( CS_DATAFMT* )); static CS_INT dsp_just _ANSI_ARGS(( CS_INT )); @@ -48,21 +57,56 @@ static void dsp_display_fmt _ANSI_ARGS(( CS_CHAR*, CS_DATAFMT* )); * it is OK for CT-Lib to do the work. This macro allows us to test * a given type as to whether or not we are going to let CT-Lib * do the dirty work. + * sqsh-2.1.8: Add CS_BINARY_TYPE and CS_IMAGE_TYPE to the list. + * Fix bugreport 3079678. + * sqsh-2.3 : Added missing data types to the list (CS_UNITEXT_TYPE, + * CS_BIGINT_TYPE,CS_USMALLINT_TYPE,CS_UINT_TYPE,CS_UBIGINT_TYPE) */ -#define LET_CTLIB_CONV(t) \ - (((t) == CS_CHAR_TYPE) || \ - ((t) == CS_TEXT_TYPE) || \ - ((t) == CS_TINYINT_TYPE) || \ - ((t) == CS_SMALLINT_TYPE) || \ - ((t) == CS_INT_TYPE) || \ - ((t) == CS_BIT_TYPE) || \ - ((t) == CS_NUMERIC_TYPE) || \ - ((t) == CS_DECIMAL_TYPE) || \ - ((t) == CS_VARCHAR_TYPE) || \ - ((t) == CS_LONGCHAR_TYPE) || \ - ((t) == CS_LONGBINARY_TYPE)|| \ - ((t) == CS_VARBINARY_TYPE) || \ - ((t) == CS_UNICHAR_TYPE)) +#if defined(CS_UNITEXT_TYPE) && defined(CS_BIGINT_TYPE) && defined(CS_USMALLINT_TYPE) && defined(CS_UINT_TYPE) && defined(CS_UBIGINT_TYPE) +#define LET_CTLIB_CONV(t) ( \ + ((t) == CS_CHAR_TYPE) \ + || ((t) == CS_BINARY_TYPE) \ + || ((t) == CS_LONGCHAR_TYPE) \ + || ((t) == CS_LONGBINARY_TYPE) \ + || ((t) == CS_TEXT_TYPE) \ + || ((t) == CS_IMAGE_TYPE) \ + || ((t) == CS_TINYINT_TYPE) \ + || ((t) == CS_SMALLINT_TYPE) \ + || ((t) == CS_INT_TYPE) \ + || ((t) == CS_BIT_TYPE) \ + || ((t) == CS_NUMERIC_TYPE) \ + || ((t) == CS_DECIMAL_TYPE) \ + || ((t) == CS_VARCHAR_TYPE) \ + || ((t) == CS_VARBINARY_TYPE) \ + || ((t) == CS_UNICHAR_TYPE) \ + || ((t) == CS_UNITEXT_TYPE) \ + || ((t) == CS_BIGINT_TYPE) \ + || ((t) == CS_USMALLINT_TYPE) \ + || ((t) == CS_UINT_TYPE) \ + || ((t) == CS_UBIGINT_TYPE) \ + || ((t) == CS_UNIQUE_TYPE) \ + ) +#else +#define LET_CTLIB_CONV(t) ( \ + ((t) == CS_CHAR_TYPE) \ + || ((t) == CS_BINARY_TYPE) \ + || ((t) == CS_LONGCHAR_TYPE) \ + || ((t) == CS_LONGBINARY_TYPE) \ + || ((t) == CS_TEXT_TYPE) \ + || ((t) == CS_IMAGE_TYPE) \ + || ((t) == CS_TINYINT_TYPE) \ + || ((t) == CS_SMALLINT_TYPE) \ + || ((t) == CS_INT_TYPE) \ + || ((t) == CS_BIT_TYPE) \ + || ((t) == CS_NUMERIC_TYPE) \ + || ((t) == CS_DECIMAL_TYPE) \ + || ((t) == CS_VARCHAR_TYPE) \ + || ((t) == CS_VARBINARY_TYPE) \ + || ((t) == CS_UNICHAR_TYPE) \ + || ((t) == CS_UNIQUE_TYPE) \ + ) +#endif + /* * dsp_desc_bind(): @@ -89,15 +133,14 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) CS_UNUSED, /* Buffer Length */ (CS_INT*)NULL) != CS_SUCCEED) { - fprintf( stderr, - "dsp_desc_bind: Unable to retrieve column count (CS_NUMDATA)\n" ); + fprintf( stderr, "dsp_desc_bind: Unable to retrieve column count (CS_NUMDATA)\n" ); return NULL; } d = (dsp_desc_t*)malloc( sizeof( dsp_desc_t ) ); c = (dsp_col_t*)malloc( sizeof( dsp_col_t ) * ncols ); - if (d == NULL || c == NULL) + if (d == NULL || c == NULL) { fprintf( stderr, "dsp_desc_bind: Memory allocation failure.\n" ); if (d != NULL) @@ -113,7 +156,7 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) d->d_bylist_size = 0; d->d_bylist = NULL; - for (i = 0; i < ncols; i++) + for (i = 0; i < ncols; i++) { d->d_cols[i].c_data = NULL; @@ -130,7 +173,7 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) d->d_cols[i].c_format.usertype = 0; d->d_cols[i].c_format.locale = NULL; } - + if (result_type == CS_COMPUTE_RESULT) { if (ct_compute_info( cmd, /* Command */ @@ -141,22 +184,19 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) (CS_INT*)NULL ) != CS_SUCCEED) { dsp_desc_destroy( d ); - fprintf( stderr, - "dsp_desc_bind: Unable to fetch by-list len of compute results\n" ); + fprintf( stderr, "dsp_desc_bind: Unable to fetch by-list len of compute results\n" ); return NULL; } if (d->d_bylist_size > 0) { - d->d_bylist = (CS_SMALLINT*)malloc( sizeof(CS_SMALLINT) * - d->d_bylist_size ); - + d->d_bylist = (CS_SMALLINT*)malloc( sizeof(CS_SMALLINT) *d->d_bylist_size ); + if (d->d_bylist == NULL) { dsp_desc_destroy( d ); - fprintf( stderr, - "dsp_desc_bind: Memory failure for by-list size array\n" ); + fprintf( stderr, "dsp_desc_bind: Memory failure for by-list size array\n" ); return NULL; } @@ -168,26 +208,24 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) (CS_INT*)NULL) != CS_SUCCEED) { dsp_desc_destroy( d ); - fprintf( stderr, - "dsp_desc_bind: Memory allocation failure for by-list array\n" ); + fprintf( stderr, "dsp_desc_bind: Memory allocation failure for by-list array\n" ); return NULL; } } } - + /* * Blast through the set of columns, binding the output to a * friendly chunk of memory. */ - for (i = 0; i < ncols; i++) + for (i = 0; i < ncols; i++) { /*-- Get description for column --*/ - if (ct_describe( cmd, i+1, &d->d_cols[i].c_format ) != CS_SUCCEED) + if (ct_describe( cmd, i+1, &d->d_cols[i].c_format ) != CS_SUCCEED) { dsp_desc_destroy( d ); - fprintf( stderr, - "dsp_desc_bind: Unable to fetch description of column #%d\n", + fprintf( stderr, "dsp_desc_bind: Unable to fetch description of column #%d\n", (int)i+1 ); return NULL; } @@ -200,9 +238,9 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) d->d_cols[i].c_data = NULL; #if 0 - /* This code has been commented out as it generates the dreaded - "bind resulted in truncation" error. */ - if (g_dsp_props.p_maxlen > 0 && + /* This code has been commented out as it generates the dreaded + "bind resulted in truncation" error. */ + if (g_dsp_props.p_maxlen > 0 && d->d_cols[i].c_maxlength > g_dsp_props.p_maxlen) { d->d_cols[i].c_maxlength = g_dsp_props.p_maxlen; @@ -219,9 +257,9 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) * request), I am forcing these data types to malloc a tad * more memory then they may need. */ - /* The amount of memory alloced used to be 64 bytes. Pushed - to 256 following discovery of buffer overflow problems by - Mike Tibbetts */ + /* The amount of memory alloced used to be 64 bytes. Pushed + to 256 following discovery of buffer overflow problems by + Mike Tibbetts */ if (d->d_cols[i].c_format.datatype == CS_FLOAT_TYPE || d->d_cols[i].c_format.datatype == CS_REAL_TYPE) { @@ -271,22 +309,22 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_desc_bind: ct_bind(\n" - " cmd = 0x%p,\n" + " cmd = %p,\n" " item = %d,\n" " fmt = [datatype = CS_CHAR_TYPE,\n" " format = CS_FMT_NULLTERM,\n" " maxlength = %d,\n" " count = 1,\n" " locale = NULL],\n" - " buf = 0x%p,\n" + " buf = %p,\n" " bytes= NULL,\n" - " ind = 0x%p)\n", - (void*)cmd, - i + 1, - (int)str_fmt.maxlength, + " ind = %p)\n", + (void*)cmd, + i + 1, + (int)str_fmt.maxlength, (void*)d->d_cols[i].c_data, (void*)&d->d_cols[i].c_nullind);) - + /* * Now, bind the incoming row to the native data type. That @@ -316,9 +354,8 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) * data prior to doing the conversion. */ d->d_cols[i].c_is_native = CS_TRUE; - d->d_cols[i].c_native = - (CS_VOID*)malloc(d->d_cols[i].c_format.maxlength); - + d->d_cols[i].c_native = (CS_VOID*)malloc(d->d_cols[i].c_format.maxlength); + if (d->d_cols[i].c_native == NULL) { fprintf( stderr, @@ -336,7 +373,7 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) DBG(sqsh_debug(DEBUG_DISPLAY, "dsp_desc_bind: ct_bind(\n" - " cmd = 0x%p,\n" + " cmd = %p,\n" " item = %d,\n" " fmt = [datatype = %d,\n" " format = %d,\n" @@ -344,12 +381,12 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) " scale = %d,\n" " precision = %d,\n" " count = %d,\n" - " locale = 0x%p],\n" - " buf = 0x%p,\n" - " bytes= 0x%p,\n" - " ind = 0x%p)\n", - (void*)cmd, - i + 1, + " locale = %p],\n" + " buf = %p,\n" + " bytes= %p,\n" + " ind = %p)\n", + (void*)cmd, + i + 1, (int)d->d_cols[i].c_format.datatype, (int)d->d_cols[i].c_format.format, (int)d->d_cols[i].c_format.maxlength, @@ -422,6 +459,7 @@ dsp_desc_t* dsp_desc_bind( cmd, result_type ) return d; } + CS_INT dsp_desc_fetch( cmd, d ) CS_COMMAND *cmd; dsp_desc_t *d; @@ -429,7 +467,12 @@ CS_INT dsp_desc_fetch( cmd, d ) CS_RETCODE r; CS_INT nrows; CS_INT i; + CS_INT j; + CS_INT p; CS_DATAFMT str_fmt; +#if defined(HAVE_LOCALE_H) + CS_CHAR *radix; +#endif if ((r = ct_fetch( cmd, /* Command */ CS_UNUSED, /* Type */ @@ -440,11 +483,11 @@ CS_INT dsp_desc_fetch( cmd, d ) return CS_END_DATA; } - /* mpeppler - 4/9/2004 - allow CS_ROW_FAIL results to go through and not abort the entire - query. CS_ROW_FAIL usually means a conversion or truncation error - which shouldn't be fatal to the entire query, although a warning - should be printed. */ + /* mpeppler - 4/9/2004 + allow CS_ROW_FAIL results to go through and not abort the entire + query. CS_ROW_FAIL usually means a conversion or truncation error + which shouldn't be fatal to the entire query, although a warning + should be printed. */ if (r != CS_SUCCEED && r != CS_ROW_FAIL) { return r; @@ -480,20 +523,63 @@ CS_INT dsp_desc_fetch( cmd, d ) * If the is_native flag is FALSE then the data was already * converted into a string for us by CT-Lib, so there is * nothing left to be done. + * sqsh-2.1.8: Except when the source datatype was binary, then + * we have to prepend the result string with characters '0x'. + * 20110107: Prepend 0x0 in case of odd number of chars in string. */ if (d->d_cols[i].c_is_native == CS_FALSE) { + if (d->d_cols[i].c_format.datatype == CS_BINARY_TYPE || + d->d_cols[i].c_format.datatype == CS_LONGBINARY_TYPE || + d->d_cols[i].c_format.datatype == CS_VARBINARY_TYPE || + d->d_cols[i].c_format.datatype == CS_IMAGE_TYPE) + { + p = strlen (d->d_cols[i].c_data); + j = (p % 2 == 0 ? 2 : 3); + for (; p >= 0; p--) + d->d_cols[i].c_data[p+j] = d->d_cols[i].c_data[p]; + d->d_cols[i].c_data[0] = '0'; + d->d_cols[i].c_data[1] = 'x'; + if (j==3) d->d_cols[i].c_data[2] = '0'; + } +#if defined(HAVE_LOCALE_H) + else if (d->d_cols[i].c_format.datatype == CS_NUMERIC_TYPE || + d->d_cols[i].c_format.datatype == CS_DECIMAL_TYPE) + { + /* + * sqsh-2.3: Convert the decimal separator in numeric/decimal datatypes + * to the character according to the locale definition of the client. + * By courtesy of Niki Hansche. + */ + if (g_lconv != NULL && (radix = (CS_CHAR *) strrchr((CS_CHAR*) (d->d_cols[i].c_data), '.')) != NULL) + { + *radix = (CS_CHAR) *g_lconv->decimal_point; + } + } +#endif continue; } + /* + * The datatype is declared native, so we have to convert it to displayable character data here. + * The case for CS_BINARY_TYPE, CS_LONGBINARY_TYPE. CS_VARBINARY_TYPE, CS_IMAGE_TYPE, + * CS_NUMERIC_TYPE and CS_DECIMAL_TYPE will only be executed if one or more of these datatypes + * are removed from the LET_CTLIB_CONV macro coded above. Otherwise these types are already + * decoded by CT-LIB. Note that freetds might have problems converting NUMERIC and DECIMAL + * types with cs_convert. + */ str_fmt.maxlength = d->d_cols[i].c_maxlength + 1; + str_fmt.precision = d->d_cols[i].c_format.precision; + str_fmt.scale = d->d_cols[i].c_format.scale; + d->d_cols[i].c_format.maxlength = d->d_cols[i].c_native_len; switch (d->d_cols[i].c_format.datatype) { case CS_BINARY_TYPE: + case CS_LONGBINARY_TYPE: + case CS_VARBINARY_TYPE: case CS_IMAGE_TYPE: strcpy( d->d_cols[i].c_data, "0x" ); - d->d_cols[i].c_format.maxlength = d->d_cols[i].c_native_len; if (cs_convert( g_context, /* Context */ &d->d_cols[i].c_format, /* Source Format */ @@ -502,54 +588,112 @@ CS_INT dsp_desc_fetch( cmd, d ) (CS_VOID*)(d->d_cols[i].c_data+2),/* Dest Data */ (CS_INT*)NULL ) == CS_FAIL) { - fprintf( stderr, - "dsp_desc_fetch: cs_convert(BIN->CHAR) column %d failed\n", - (int)i+1 ); + fprintf( stderr, "dsp_desc_fetch: cs_convert(BIN->CHAR) column %d failed\n", (int) i+1 ); + dsp_display_fmt( "src_fmt", &d->d_cols[i].c_format ); + dsp_display_fmt( "dst_fmt", &str_fmt ); + return CS_FAIL; + } + break; + + case CS_NUMERIC_TYPE: + case CS_DECIMAL_TYPE: + if (cs_convert( g_context, /* Context */ + &d->d_cols[i].c_format, /* Source Format */ + d->d_cols[i].c_native, /* Source Data */ + &str_fmt, /* Dest Format */ + (CS_VOID*)(d->d_cols[i].c_data),/* Dest Data */ + (CS_INT*)NULL ) == CS_FAIL) + { + fprintf( stderr, "dsp_desc_fetch: cs_convert(NUMERIC->CHAR) column %d failed\n", (int) i+1 ); + dsp_display_fmt( "src_fmt", &d->d_cols[i].c_format ); + dsp_display_fmt( "dst_fmt", &str_fmt ); + return CS_FAIL; + } + +#if defined(HAVE_LOCALE_H) + /* + * sqsh-2.3: Convert the decimal separator in numeric/decimal datatypes + * to the character according to the locale definition of the client. + * By courtesy of Niki Hansche. + */ + if (g_lconv != NULL && (radix = (CS_CHAR *) strrchr((CS_CHAR*) (d->d_cols[i].c_data), '.')) != NULL) + { + *radix = (CS_CHAR) *g_lconv->decimal_point; + } +#endif + break; + + case CS_MONEY_TYPE: + case CS_MONEY4_TYPE: + if (cs_convert( g_context, /* Context */ + &d->d_cols[i].c_format, /* Source Format */ + d->d_cols[i].c_native, /* Source Data */ + &str_fmt, /* Dest Format */ + (CS_VOID*)(d->d_cols[i].c_data),/* Dest Data */ + (CS_INT*)NULL ) == CS_FAIL) + { + fprintf( stderr, "dsp_desc_fetch: cs_convert(MONEY->CHAR) column %d failed\n", (int) i+1 ); dsp_display_fmt( "src_fmt", &d->d_cols[i].c_format ); dsp_display_fmt( "dst_fmt", &str_fmt ); return CS_FAIL; } + +#if defined(HAVE_LOCALE_H) + /* + * sqsh-2.3: Convert the decimal separator in money datatypes + * to the character according to the locale definition of the client. + * By courtesy of Niki Hansche. + */ + if (g_lconv != NULL && (radix = (CS_CHAR *) strrchr((CS_CHAR*) (d->d_cols[i].c_data), '.')) != NULL) + { + *radix = (CS_CHAR) *g_lconv->mon_decimal_point; + } +#endif break; case CS_REAL_TYPE: - sprintf( (char*)d->d_cols[i].c_data, "%*.*f", + sprintf( (char*)d->d_cols[i].c_data, "%*.*f", g_dsp_props.p_real_prec + 2, g_dsp_props.p_real_scale, (double)(*((CS_REAL*)d->d_cols[i].c_native)) ); break; case CS_FLOAT_TYPE: - sprintf( (char*)d->d_cols[i].c_data, "%*.*f", + sprintf( (char*)d->d_cols[i].c_data, "%*.*f", g_dsp_props.p_flt_prec + 2, g_dsp_props.p_flt_scale, (double)(*((CS_FLOAT*)d->d_cols[i].c_native)) ); break; + /* + * sqsh-2.1.9 - Also take date and time datatypes into consideration + */ case CS_DATETIME_TYPE: case CS_DATETIME4_TYPE: #if defined(CS_DATE_TYPE) - case CS_DATE_TYPE: + case CS_DATE_TYPE: #endif #if defined(CS_TIME_TYPE) - case CS_TIME_TYPE: + case CS_TIME_TYPE: +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: #endif -#if defined(CS_BIGDATETIME) - case CS_BIGDATETIME_TYPE: - case CS_BIGTIME_TYPE: +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: #endif if (dsp_datetime_conv( g_context, /* Context */ - &d->d_cols[i].c_format, /* Data format */ + &d->d_cols[i].c_format, /* Data format */ d->d_cols[i].c_native, /* Data */ d->d_cols[i].c_data, /* Destination */ - d->d_cols[i].c_maxlength+1 ) != CS_SUCCEED) + d->d_cols[i].c_maxlength+1, + d->d_cols[i].c_format.datatype ) != CS_SUCCEED) { return CS_FAIL; } break; - - default: - d->d_cols[i].c_format.maxlength = d->d_cols[i].c_native_len; + default: if (cs_convert( g_context, /* Context */ &d->d_cols[i].c_format, /* Source Format */ d->d_cols[i].c_native, /* Source Data */ @@ -557,9 +701,10 @@ CS_INT dsp_desc_fetch( cmd, d ) (CS_VOID*)d->d_cols[i].c_data, /* Dest Data */ (CS_INT*)NULL ) != CS_SUCCEED) { - fprintf( stderr, - "dsp_desc_fetch: cs_convert(%d->CHAR) column %d failed\n", - (int)d->d_cols[i].c_format.datatype, (int)i+1 ); + fprintf( stderr, "dsp_desc_fetch: cs_convert(%d->CHAR) column %d failed\n", + (int) d->d_cols[i].c_format.datatype, (int) i+1 ); + dsp_display_fmt( "src_fmt", &d->d_cols[i].c_format ); + dsp_display_fmt( "dst_fmt", &str_fmt ); return CS_FAIL; } break; @@ -580,11 +725,11 @@ void dsp_desc_destroy( d ) { CS_INT i; - if (d != NULL) + if (d != NULL) { - if (d->d_cols != NULL) + if (d->d_cols != NULL) { - for (i = 0; i < d->d_ncols; i++) + for (i = 0; i < d->d_ncols; i++) { if (d->d_cols[i].c_native != NULL) { @@ -607,6 +752,7 @@ void dsp_desc_destroy( d ) } } + static void dsp_display_fmt( nm, f ) CS_CHAR *nm; CS_DATAFMT *f; @@ -614,35 +760,25 @@ static void dsp_display_fmt( nm, f ) if (f->namelen > 0 && f->namelen < CS_MAX_NAME) { fprintf( stderr, "%s->name = %*.*s\n", - (char*)nm, (int)f->namelen, (int)f->namelen, (char*)f->name ); + (char*) nm, (int) f->namelen, (int) f->namelen, (char*) f->name ); } else { - fprintf( stderr, "%s->name = <empty>\n", - (char*)nm ); + fprintf( stderr, "%s->name = <empty>\n", (char*)nm ); } - fprintf( stderr, "%s->namelen = %d\n", - (char*)nm, (int)f->namelen ); - fprintf( stderr, "%s->datatype = %d\n", - (char*)nm, (int)f->datatype ); - fprintf( stderr, "%s->format = %d\n", - (char*)nm, (int)f->format ); - fprintf( stderr, "%s->maxlength = %d\n", - (char*)nm, (int)f->maxlength ); - fprintf( stderr, "%s->scale = %d\n", - (char*)nm, (int)f->scale ); - fprintf( stderr, "%s->precision = %d\n", - (char*)nm, (int)f->precision ); - fprintf( stderr, "%s->status = %d\n", - (char*)nm, (int)f->status ); - fprintf( stderr, "%s->count = %d\n", - (char*)nm, (int)f->count ); - fprintf( stderr, "%s->usertype = %d\n", - (char*)nm, (int)f->usertype ); - fprintf( stderr, "%s->locale = 0x%p\n", - (char*)nm, (void*)f->locale ); + fprintf( stderr, "%s->namelen = %d\n", (char*) nm, (int) f->namelen ); + fprintf( stderr, "%s->datatype = %d\n", (char*) nm, (int) f->datatype ); + fprintf( stderr, "%s->format = %d\n", (char*) nm, (int) f->format ); + fprintf( stderr, "%s->maxlength = %d\n", (char*) nm, (int) f->maxlength); + fprintf( stderr, "%s->scale = %d\n", (char*) nm, (int) f->scale ); + fprintf( stderr, "%s->precision = %d\n", (char*) nm, (int) f->precision); + fprintf( stderr, "%s->status = %d\n", (char*) nm, (int) f->status ); + fprintf( stderr, "%s->count = %d\n", (char*) nm, (int) f->count ); + fprintf( stderr, "%s->usertype = %d\n", (char*) nm, (int) f->usertype ); + fprintf( stderr, "%s->locale = %p\n", (char*) nm, (void*) f->locale ); } + /* * dsp_just(): * @@ -651,21 +787,44 @@ static void dsp_display_fmt( nm, f ) static CS_INT dsp_just( type ) CS_INT type; { - switch (type) + switch (type) { - case CS_BIT_TYPE: case CS_TINYINT_TYPE: case CS_SMALLINT_TYPE: case CS_INT_TYPE: case CS_REAL_TYPE: case CS_FLOAT_TYPE: + case CS_BIT_TYPE: + case CS_DATETIME_TYPE: + case CS_DATETIME4_TYPE: case CS_MONEY_TYPE: case CS_MONEY4_TYPE: case CS_NUMERIC_TYPE: case CS_DECIMAL_TYPE: - case CS_DATETIME_TYPE: - case CS_DATETIME4_TYPE: - case CS_BINARY_TYPE: +#if defined(CS_DATE_TYPE) + case CS_DATE_TYPE: +#endif +#if defined(CS_TIME_TYPE) + case CS_TIME_TYPE: +#endif +#if defined(CS_BIGINT_TYPE) + case CS_BIGINT_TYPE: +#endif +#if defined(CS_USMALLINT_TYPE) + case CS_USMALLINT_TYPE: +#endif +#if defined(CS_UINT_TYPE) + case CS_UINT_TYPE: +#endif +#if defined(CS_UBIGINT_TYPE) + case CS_UBIGINT_TYPE: +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: +#endif return DSP_JUST_RIGHT; default: break; @@ -684,21 +843,27 @@ static CS_INT dsp_just( type ) static CS_INT dsp_dlen( fmt ) CS_DATAFMT *fmt; { - switch (fmt->datatype) + switch (fmt->datatype) { case CS_CHAR_TYPE: case CS_LONGCHAR_TYPE: case CS_TEXT_TYPE: case CS_VARCHAR_TYPE: + case CS_UNICHAR_TYPE: +#if defined(CS_UNITEXT_TYPE) + case CS_UNITEXT_TYPE: +#endif +#if defined(CS_XML_TYPE) + case CS_XML_TYPE: +#endif return fmt->maxlength; - case CS_IMAGE_TYPE: + case CS_BINARY_TYPE: case CS_LONGBINARY_TYPE: + case CS_IMAGE_TYPE: case CS_VARBINARY_TYPE: - case CS_UNICHAR_TYPE: - return (2 * fmt->maxlength) + 4; - case CS_BIT_TYPE: - return 1; + return (2 * fmt->maxlength) + 2; /* sqsh-2.1.8 fix */ + case CS_TINYINT_TYPE: return 3; case CS_SMALLINT_TYPE: @@ -711,22 +876,51 @@ static CS_INT dsp_dlen( fmt ) case CS_FLOAT_TYPE: /*-- Sign + Decimal + Precision --*/ return 2 + g_dsp_props.p_flt_prec; + case CS_BIT_TYPE: + return 1; + case CS_MONEY4_TYPE: return dsp_money4_len( g_context ); case CS_MONEY_TYPE: return dsp_money_len( g_context ); + case CS_NUMERIC_TYPE: + case CS_DECIMAL_TYPE: + return (fmt->precision + 3); + case CS_DATETIME_TYPE: case CS_DATETIME4_TYPE: #if defined(CS_DATE_TYPE) - case CS_DATE_TYPE: + case CS_DATE_TYPE: #endif #if defined(CS_TIME_TYPE) - case CS_TIME_TYPE: + case CS_TIME_TYPE: +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: #endif return dsp_datetime_len( g_context, fmt->datatype); - case CS_NUMERIC_TYPE: - case CS_DECIMAL_TYPE: - return (fmt->precision + 3); + +#if defined(CS_BIGINT_TYPE) + case CS_BIGINT_TYPE: + return 20; +#endif +#if defined(CS_USMALLINT_TYPE) + case CS_USMALLINT_TYPE: + return 5; +#endif +#if defined(CS_UINT_TYPE) + case CS_UINT_TYPE: + return 10; +#endif +#if defined(CS_UBIGINT_TYPE) + case CS_UBIGINT_TYPE: + return 20; +#endif + case CS_UNIQUE_TYPE: + return 36; default: break; } diff --git a/src/dsp_html.c b/src/dsp_html.c index a227869..1a051fb 100644 --- a/src/dsp_html.c +++ b/src/dsp_html.c @@ -34,7 +34,7 @@ extern int errno; /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_html.c,v 1.2 2004/04/11 15:14:32 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_html.c,v 1.4 2013/08/21 11:16:39 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -125,7 +125,7 @@ int dsp_html( output, cmd, flags ) case CS_STATUS_RESULT: if (in_table == CS_TRUE) { - dsp_fputs( "</table>\n", output ); + dsp_fputs( "</tbody>\n</table>\n", output ); in_table = CS_FALSE; } @@ -197,7 +197,7 @@ int dsp_html( output, cmd, flags ) if (in_table == CS_TRUE) { - dsp_fputs( "</table>\n", output ); + dsp_fputs( "</tbody>\n</table>\n", output ); } if (rows_affected != CS_NO_COUNT && !(flags & DSP_F_NOFOOTERS)) @@ -230,7 +230,7 @@ int dsp_html( output, cmd, flags ) if (select_desc == NULL) goto dsp_fail; - dsp_fputs( "\n<table border>\n", output ); + dsp_fputs( "\n<table class=\"sqshtable\" border=\"1\">\n", output ); in_table = CS_TRUE; /* @@ -241,7 +241,7 @@ int dsp_html( output, cmd, flags ) if (g_dsp_interrupted) goto dsp_interrupted; - dsp_fputs( "<tr>\n", output ); + dsp_fputs( "<thead>\n<tr>\n", output ); for (i = 0; i < select_desc->d_ncols; i++) { col = &select_desc->d_cols[i]; @@ -257,7 +257,7 @@ int dsp_html( output, cmd, flags ) } dsp_fputs( "</th>\n", output ); } - dsp_fputs( "</tr>\n", output ); + dsp_fputs( "</tr>\n</thead><tbody>\n", output ); } if (g_dsp_interrupted) @@ -279,11 +279,11 @@ int dsp_html( output, cmd, flags ) if (col->c_justification == DSP_JUST_RIGHT) { - dsp_fputs( " <td align=right>", output ); + dsp_fputs( " <td style=\"text-align: right;\">", output ); } else { - dsp_fputs( " <td align=left>", output ); + dsp_fputs( " <td style=\"text-align: left;\">", output ); } if (col->c_nullind == -1) @@ -358,7 +358,7 @@ int dsp_html( output, cmd, flags ) if (in_table == CS_TRUE) { - dsp_fputs( "</table>\n", output ); + dsp_fputs( "</tbody></table>\n", output ); } if (last_row_result != CS_STATUS_RESULT && rows_affected != CS_NO_COUNT && @@ -434,7 +434,7 @@ static CS_INT dsp_comp_prrow_one( output, sel_desc, com_desc ) dsp_col_t *sel_col; dsp_col_t *com_col; - dsp_fputs( "<tr>\n", output ); + dsp_fputs( "<thead>\n<tr>\n", output ); for (i = 0; i < sel_desc->d_ncols; i++) { dsp_fputs( " <th>", output ); @@ -462,9 +462,9 @@ static CS_INT dsp_comp_prrow_one( output, sel_desc, com_desc ) dsp_fputs( "</th>", output ); } - dsp_fputs( "</tr>\n", output ); + dsp_fputs( "</tr>\n</thead><tbody>\n", output ); - dsp_fputs( "<tr>\n", output ); + dsp_fputs( "<tbody>\n<tr>\n", output ); for (i = 0; i < sel_desc->d_ncols; i++) { /*-- Handy Pointer --*/ @@ -472,11 +472,11 @@ static CS_INT dsp_comp_prrow_one( output, sel_desc, com_desc ) if (sel_col->c_justification == DSP_JUST_RIGHT) { - dsp_fputs( " <td align=right>", output ); + dsp_fputs( " <td style=\"text-align: right;\">", output ); } else { - dsp_fputs( " <td align=left>", output ); + dsp_fputs( " <td style=\"text-align: left;\">", output ); } /* @@ -503,7 +503,7 @@ static CS_INT dsp_comp_prrow_one( output, sel_desc, com_desc ) dsp_fputs( "<br>", output ); } } - dsp_fputs( "</tr>\n", output ); + dsp_fputs( "</tr>\n</tbody>\n", output ); return count; } diff --git a/src/dsp_meta.c b/src/dsp_meta.c index 9beb88c..8759806 100644 --- a/src/dsp_meta.c +++ b/src/dsp_meta.c @@ -32,7 +32,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_meta.c,v 1.3 2004/04/11 15:14:32 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_meta.c,v 1.5 2013/12/03 09:22:23 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -370,6 +370,18 @@ static CS_CHAR* dsp_meta_status( s, fmt ) strcat( fmt, "CS_RETURN" ); } +#if defined(CS_RETURN_CANBENULL) + if (s & CS_RETURN_CANBENULL) + { + if (need_comma) + { + strcat(fmt, "," ); + } + need_comma = CS_TRUE; + + strcat( fmt, "CS_RETURN_CANBENULL" ); + } +#endif if (s & CS_TIMESTAMP) { if (need_comma) @@ -532,14 +544,6 @@ static CS_CHAR* dsp_meta_datatype( t ) return "CS_DATETIME_TYPE"; case CS_DATETIME4_TYPE: return "CS_DATETIME4_TYPE"; -#if defined(CS_DATE_TYPE) - case CS_DATE_TYPE: - return "CS_DATE_TYPE"; -#endif -#if defined(CS_TIME_TYPE) - case CS_TIME_TYPE: - return "CS_TIME_TYPE"; -#endif case CS_MONEY_TYPE: return "CS_MONEY_TYPE"; case CS_MONEY4_TYPE: @@ -562,6 +566,58 @@ static CS_CHAR* dsp_meta_datatype( t ) return "CS_VOID_TYPE"; case CS_USHORT_TYPE: return "CS_USHORT_TYPE"; +#if defined(CS_UNICHAR_TYPE) + case CS_UNICHAR_TYPE: + return "CS_UNICHAR_TYPE"; +#endif +#if defined(CS_BLOB_TYPE) + case CS_BLOB_TYPE: + return "CS_BLOB_TYPE"; +#endif +#if defined(CS_DATE_TYPE) + case CS_DATE_TYPE: + return "CS_DATE_TYPE"; +#endif +#if defined(CS_TIME_TYPE) + case CS_TIME_TYPE: + return "CS_TIME_TYPE"; +#endif +#if defined(CS_UNITEXT_TYPE) + case CS_UNITEXT_TYPE: + return "CS_UNITEXT_TYPE"; +#endif +#if defined(CS_BIGINT_TYPE) + case CS_BIGINT_TYPE: + return "CS_BIGINT_TYPE"; +#endif +#if defined(CS_USMALLINT_TYPE) + case CS_USMALLINT_TYPE: + return "CS_USMALLINT_TYPE"; +#endif +#if defined(CS_UINT_TYPE) + case CS_UINT_TYPE: + return "CS_UINT_TYPE"; +#endif +#if defined(CS_UBIGINT_TYPE) + case CS_UBIGINT_TYPE: + return "CS_UBIGINT_TYPE"; +#endif +#if defined(CS_XML_TYPE) + case CS_XML_TYPE: + return "CS_XML_TYPE"; +#endif +#if defined(CS_BIGDATETIME_TYPE) + case CS_BIGDATETIME_TYPE: + return "CS_BIGDATETIME_TYPE"; +#endif +#if defined(CS_BIGTIME_TYPE) + case CS_BIGTIME_TYPE: + return "CS_BIGTIME_TYPE"; +#endif +#if defined(CS_UNIQUE_TYPE) + case CS_UNIQUE_TYPE: + return "CS_UNIQUE_TYPE"; +#endif default: break; } diff --git a/src/dsp_pretty.c b/src/dsp_pretty.c index 06cb9bd..e274b41 100644 --- a/src/dsp_pretty.c +++ b/src/dsp_pretty.c @@ -34,7 +34,7 @@ extern int errno; /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_pretty.c,v 1.3 2005/11/19 16:51:11 mpeppler Exp $"; +static char RCS_Id[] = "$Id: dsp_pretty.c,v 1.4 2014/01/18 18:36:34 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -279,6 +279,8 @@ int dsp_pretty( o, cmd, flags ) /* * Then, while there is data to fetch, display the * data for each row as it comes back. + * sqsh-2.5: Suppress printing of a separator line when the flag + * DSP_F_NOSEPLINE is enabled using the -l option with \go -mpretty. */ while ((ret = dsp_desc_fetch( cmd, select_desc )) == CS_SUCCEED) { @@ -286,10 +288,14 @@ int dsp_pretty( o, cmd, flags ) goto dsp_interrupted; dsp_prrow( o, select_desc ); + if (!(flags & DSP_F_NOSEPLINE)) + dsp_prsep( o, select_desc, (int)'-' ); if (g_dsp_interrupted) goto dsp_interrupted; } + if ((flags & DSP_F_NOSEPLINE) && !(flags & DSP_F_NOFOOTERS)) + dsp_prsep( o, select_desc, (int)'-' ); if (ret != CS_END_DATA) { @@ -621,8 +627,6 @@ static void dsp_prrow( output, desc ) } while (done == False); - dsp_prsep( output, desc, (int)'-' ); - return; } diff --git a/src/dsp_x.c b/src/dsp_x.c index 121b4a0..c1b2228 100644 --- a/src/dsp_x.c +++ b/src/dsp_x.c @@ -29,14 +29,16 @@ #include <stdio.h> #include <ctype.h> #include "sqsh_config.h" +#include "sqsh_debug.h" #include "sqsh_error.h" +#include "sqsh_expand.h" #include "sqsh_global.h" -#include "sqsh_debug.h" +#include "sqsh_init.h" #include "dsp.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: dsp_x.c,v 1.6 2010/02/08 13:25:48 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: dsp_x.c,v 1.8 2013/05/07 21:18:02 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -114,7 +116,7 @@ int dsp_x( output, cmd, flags, dsp_func ) else { i = 0; - for (cp = g_dsp_props.p_xgeom; *cp != '\0' && isdigit(*cp); ++cp) + for (cp = g_dsp_props.p_xgeom; *cp != '\0' && isdigit( (int) *cp); ++cp) { number[i++] = *cp; } @@ -251,7 +253,6 @@ static int dsp_x_init( fd, width, height ) int width; int height; { - int i; int nlines; /*-- Widgets that make up our window --*/ @@ -265,17 +266,14 @@ static int dsp_x_init( fd, width, height ) Widget w_btn_form; Widget w_btn_ok; XmString s_ok; - XmString s_cancel; cb_data_t cd; /* Data for callbacks */ XtInputId id; /* Id of input source */ Dimension dim; - int text_width; - int orig_width; int argc; char *argv[1]; char *cp; char *xwin_title = NULL; - varbuf_t *exp_buf; + varbuf_t *exp_buf = NULL; /* * At this point we are in the child process, the rest is pretty @@ -419,7 +417,8 @@ static int dsp_x_init( fd, width, height ) NULL); XtMainLoop(); - varbuf_destroy( exp_buf ); + if (exp_buf != NULL) + varbuf_destroy( exp_buf ); exit(0); } @@ -435,12 +434,9 @@ static void dsp_x_input_cb (client_data, fd, id) int *fd; XtInputId *id; { - static int len = 0; /* Total Length of text in widget */ char buffer[2048]; /* Read up to 2K of input */ int n; cb_data_t *cd; - char *cp; - char number[20]; cd = (cb_data_t*)client_data; @@ -524,7 +520,7 @@ static int dsp_x_init( fd, width, height ) int argc; char *argv[1]; char *xwin_title = NULL; - varbuf_t *exp_buf; + varbuf_t *exp_buf = NULL; XFontStruct *font = NULL; /* Font for text widget */ @@ -640,7 +636,8 @@ static int dsp_x_init( fd, width, height ) XtRealizeWidget( w_top ); XtMainLoop(); - varbuf_destroy( exp_buf ); + if (exp_buf != NULL) + varbuf_destroy( exp_buf ); exit(0); } diff --git a/src/sqsh b/src/sqsh Binary files differdeleted file mode 100755 index 7dbc9d0..0000000 --- a/src/sqsh +++ /dev/null diff --git a/src/sqsh_buf.c b/src/sqsh_buf.c index 0562ba1..1667b27 100644 --- a/src/sqsh_buf.c +++ b/src/sqsh_buf.c @@ -29,18 +29,14 @@ #include "sqsh_error.h" #include "sqsh_stdin.h" #include "sqsh_buf.h" +#include "sqsh_readline.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_buf.c,v 1.3 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_buf.c,v 1.4 2012/03/14 09:17:51 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ -#if defined(USE_READLINE) -#include <readline/readline.h> -extern void add_history(); -#endif /* USE_READLINE */ - /* * Note: This whole module is quite a bit different from all other * sqsh_*.c modules, in that it provides no real data for itself. diff --git a/src/sqsh_config.h b/src/sqsh_config.h index 1f22fe1..f7e2bf0 100644 --- a/src/sqsh_config.h +++ b/src/sqsh_config.h @@ -34,9 +34,10 @@ * The maximum length of a password. I just pulled this one out of * the air. * sqsh-2.1.6 - Increased value from 12 to 30 + * sqsh-2.4 - Increased value from 30 to 64 */ #ifndef SQSH_PASSLEN -#define SQSH_PASSLEN 30 +#define SQSH_PASSLEN 64 #endif /* @@ -128,6 +129,19 @@ #define SQSH_MAXFD 256 #endif +#if defined(USE_READLINE) +/* + * sqsh-2.1.8 - Define the default query that will be executed in + * case keyword_dynamic is enabled and an interactive connection is setup + * to a Sybase ASE or Microsoft MSSQL database server, or the database + * context is changed due to a "use" command. + * + */ +# ifndef SQSH_KEYQUERY +# define SQSH_KEYQUERY "select name from sysobjects order by name" +# endif +#endif + /* * End user configuration section */ @@ -135,7 +149,7 @@ /* * Current version number. */ -#define SQSH_VERSION "sqsh-2.1.7" +#define SQSH_VERSION "sqsh-2.5.16.1" #if !defined(__ansi__) # if defined(__STDC__) || defined(STDC_HEADERS) || defined(PROTOTYPES) diff --git a/src/sqsh_ctx.c b/src/sqsh_ctx.c deleted file mode 100644 index 0149e9e..0000000 --- a/src/sqsh_ctx.c +++ /dev/null @@ -1,334 +0,0 @@ -/* -** sqsh_ctx.c - Manipulate a context of execution. -** -** Copyright (C) 1995, 1996 by Scott C. Gray -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, write to the Free Software -** Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -** -** You may contact the author : -** e-mail: gray@voicenet.com -** grays@xtend-tech.com -** gray@xenotropic.com -*/ -#include <stdio.h> -#include "sqsh_config.h" -#include "sqsh_error.h" -#include "sqsh_ctx.h" - -/* -** sqsh_ctx_t: This data structure is used to hold the context of -** a sqsh block. -*/ -typedef struct sqsh_ctx_st -{ - int ctx_argc; /* Argument count to current context */ - char **ctx_argv; /* Array of arguments */ - CS_CONNECTION *ctx_conn; /* Connection to the database */ - dsp_desc_t *ctx_cols; /* Columns referenced from \do loop */ - varbuf_t *ctx_sqlbuf; /* Current SQL command */ - struct sqsh_ctx_st *ctx_prev; /* Previous context */ -} -sqsh_ctx_t; - -/* -** sg_cur_ctx: Pointer to the current execution context. -*/ -static sqsh_ctx_t *sg_cur_ctx; - -/* -** sqsh_ctx_push(): -** -** Allocates a new execution context. -*/ -int sqsh_ctx_push() -{ - sqsh_ctx_t *ctx; - - ctx = (sqsh_ctx_t*)malloc(sizeof(sqsh_ctx_t)); - - if (ctx == NULL) - { - sqsh_set_error( SQSH_E_NOMEM, - "sqsh_ctx_push: Memory allocation failure\n" ); - return(False); - } - - ctx->ctx_argc = -1; - ctx->ctx_argv = NULL; - ctx->ctx_conn = NULL; - ctx->ctx_cols = NULL; - ctx->ctx_sqlbuf = NULL; - ctx->ctx_prev = sg_cur_ctx; - - sg_cur_ctx = ctx; - return(True); -} - -/* -** sqsh_ctx_pop(): -** -** Discard the current context and return to the previous one. -** This will automatically close any connection and the -** current column descriptions and sqlbuffer for the -** context. -*/ -int sqsh_ctx_pop() -{ - sqsh_ctx_t *ctx; - CS_INT conn_status; - - if (sg_cur_ctx == NULL) - { - fprintf( stderr, - "sqsh_ctx_pop: No more contexts left!\n" ); - return(False); - } - - ctx = sg_cur_ctx; - sg_cur_ctx = sg_cur_ctx->ctx_prev; - - if (ctx->ctx_conn != NULL) - { - if (ct_con_props( ctx->ctx_conn, CS_GET, CS_CON_STATUS, - (CS_VOID*)&conn_status, CS_UNUSED, (CS_INT*)NULL ) != CS_SUCCEED) - { - conn_status = CS_CONSTAT_CONNECTED; - } - - if ((conn_status & CS_CONSTAT_CONNECTED) - == CS_CONSTAT_CONNECTED) - { - ct_close( ctx->ctx_conn, CS_FORCE_CLOSE ); - } - - ct_con_drop( ctx->ctx_conn ); - } - - if (ctx->ctx_cols != NULL) - { - dsp_desc_destroy( ctx->ctx_cols ); - } - - if (ctx->ctx_sqlbuf != NULL) - { - varbuf_destroy( ctx->ctx_sqlbuf ); - } - - free( ctx ); - return(True); -} - -/* -** sqsh_ctx_set_args(): -** -** Set an argument set for the current context. Note that -** the argv[] array will not be freed when the context -** returns. This is the duty of the function that allocated -** the context. -*/ -int sqsh_ctx_set_args (argc, argv) - int argc; - char *argv[]; -{ - if (sg_cur_ctx == NULL) - { - fprintf( stderr, - "sqsh_ctx_set_args: There is no available execution context!\n" ); - return(False); - } - - sg_cur_ctx->ctx_argc = argc; - sg_cur_ctx->ctx_argv = argv; - return(True); -} - -/* -** sqsh_ctx_get_args(): -** -** Fetch the current argument list. -*/ -int sqsh_ctx_get_args (argc, argv) - int *argc; - char ***argv; -{ - sqsh_ctx_t *ctx; - - for (ctx = sg_cur_ctx; ctx != NULL; ctx = ctx->ctx_prev) - { - if (ctx->ctx_argv != NULL && ctx->ctx_argc >= 0) - { - *argc = ctx->ctx_argc; - *argv = ctx->ctx_argv; - return(True); - } - } - - *argc = -1; - *argv = NULL; - return(False); -} - -/* -** sqsh_ctx_set_conn(): -** -** Attaches a connection to the current context. This connection -** will automatically be closed and destroyed when the current -** context is dropped. -*/ -int sqsh_ctx_set_conn (conn) - CS_CONNECTION *conn; -{ - if (sg_cur_ctx == NULL) - { - fprintf( stderr, - "sqsh_ctx_set_conn: There is no available execution context!\n" ); - return(False); - } - - if (sg_cur_ctx->ctx_conn != NULL) - { - fprintf( stderr, - "sqsh_ctx_set_conn: There is already an attached connectioN!\n" ); - return(False); - } - - sg_cur_ctx->ctx_conn = conn; - return(True); -} - -/* -** sqsh_ctx_get_conn(): -** -** Fetch the current connection. -*/ -int sqsh_ctx_get_conn (conn) - CS_CONNECTION **conn; -{ - sqsh_ctx_t *ctx; - - for (ctx = sg_cur_ctx; ctx != NULL; ctx = ctx->ctx_prev) - { - if (ctx->ctx_conn != NULL) - { - *conn = ctx->ctx_conn; - return(True); - } - } - - *conn = NULL; - return(False); -} - -/* -** sqsh_ctx_set_cols(): -** -** Attaches a description of the a result set to the current context. -** This is only utilized by the \do loop right now. -*/ -int sqsh_ctx_set_cols (desc) - dsp_desc_t *desc; -{ - if (sg_cur_ctx == NULL) - { - fprintf( stderr, - "sqsh_ctx_set_cols: There is no available execution context!\n" ); - return(False); - } - - if (sg_cur_ctx->ctx_cols != NULL) - { - fprintf( stderr, - "sqsh_ctx_set_cols: There is already a column description in the " - "current exuection context!\n" ); - return(False); - } - - sg_cur_ctx->ctx_cols = desc; - return(True); -} - -/* -** sqsh_ctx_get_cols(): -** -** Fetch the current column set.. -*/ -int sqsh_ctx_get_cols (desc) - dsp_desc_t **desc; -{ - sqsh_ctx_t *ctx; - - for (ctx = sg_cur_ctx; ctx != NULL; ctx = ctx->ctx_prev) - { - if (ctx->ctx_cols != NULL) - { - *desc = ctx->ctx_cols; - return(True); - } - } - - *desc = NULL; - return(False); -} - -/* -** sqsh_ctx_set_sqlbuf(): -** -** Attach a new SQL buffer to the current context. -*/ -int sqsh_ctx_set_sqlbuf (sqlbuf) - varbuf_t *sqlbuf; -{ - if (sg_cur_ctx == NULL) - { - fprintf( stderr, - "sqsh_ctx_set_sqlbuf: There is no available execution context!\n" ); - return(False); - } - - if (sg_cur_ctx->ctx_sqlbuf != NULL) - { - fprintf( stderr, - "sqsh_ctx_set_cols: There is already a sql buffer in the " - "current exuection context!\n" ); - return(False); - } - - sg_cur_ctx->ctx_sqlbuf = sqlbuf; - return(True); -} - -/* -** sqsh_ctx_get_sqlbuf(): -** -** Get the current sql buffer. -*/ -int sqsh_ctx_get_sqlbuf (sqlbuf) - varbuf_t **sqlbuf; -{ - sqsh_ctx_t *ctx; - - for (ctx = sg_cur_ctx; ctx != NULL; ctx = ctx->ctx_prev) - { - if (ctx->ctx_sqlbuf != NULL) - { - *sqlbuf = ctx->ctx_sqlbuf; - return(True); - } - } - - *sqlbuf = NULL; - return(False); - -} diff --git a/src/sqsh_ctx.h b/src/sqsh_ctx.h deleted file mode 100644 index 9b4bed5..0000000 --- a/src/sqsh_ctx.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef sqsh_ctx_h_included -#define sqsh_ctx_h_included -#include <ctpublic.h> -#include "sqsh_varbuf.h" -#include "dsp.h" - -/* -** Prototypes for manipulating the context. -*/ -int sqsh_ctx_push _ANSI_ARGS(( void )); -int sqsh_ctx_set_args _ANSI_ARGS(( int, char** )); -int sqsh_ctx_get_args _ANSI_ARGS(( int*, char*** )); -int sqsh_ctx_set_conn _ANSI_ARGS(( CS_CONNECTION* )); -int sqsh_ctx_get_conn _ANSI_ARGS(( CS_CONNECTION** )); -int sqsh_ctx_set_cols _ANSI_ARGS(( dsp_desc_t* )); -int sqsh_ctx_get_cols _ANSI_ARGS(( dsp_desc_t** )); -int sqsh_ctx_set_sqlbuf _ANSI_ARGS(( varbuf_t* )); -int sqsh_ctx_get_sqlbuf _ANSI_ARGS(( varbuf_t** )); -int sqsh_ctx_pop _ANSI_ARGS(( void )); - -#endif /* sqsh_ctx_h_included */ diff --git a/src/sqsh_debug.c b/src/sqsh_debug.c index b5c9d51..a91ebbc 100644 --- a/src/sqsh_debug.c +++ b/src/sqsh_debug.c @@ -34,7 +34,7 @@ #endif #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_debug.c,v 1.1.1.1 2004/04/07 12:35:05 chunkm0nkey Exp $" ; +static char RCS_Id[] = "$Id: sqsh_debug.c,v 1.3 2013/05/05 19:50:43 mwesdorp Exp $" ; USE(RCS_Id) #endif @@ -92,3 +92,20 @@ void sqsh_debug( debug_mask, fmt, va_alist ) return ; } +#if defined(__ansi__) +int sqsh_debug_show( int debug_mask ) +#else +int sqsh_debug_show( debug_mask ) + int debug_mask ; +#endif +{ +#if defined(DEBUG) + if( debug_mask == DEBUG_ALL || (debug_mask & sg_debug_level) ) + return True; + else + return False; +#else + return False; +#endif /* DEBUG */ +} + diff --git a/src/sqsh_debug.h b/src/sqsh_debug.h index 315ea5e..be06006 100644 --- a/src/sqsh_debug.h +++ b/src/sqsh_debug.h @@ -39,6 +39,8 @@ #define DEBUG_RPC (1<<11) /* Debug the rpc command */ #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) @@ -48,6 +50,7 @@ #endif int sqsh_debug_level _ANSI_ARGS(( int )) ; +int sqsh_debug_show _ANSI_ARGS(( int )) ; void sqsh_debug _ANSI_ARGS(( int, char*, ... )) ; #endif /* sqsh_debug_h_included */ diff --git a/src/sqsh_env.c b/src/sqsh_env.c index dee4940..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.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 06d0a35..d2150de 100644 --- a/src/sqsh_expand.c +++ b/src/sqsh_expand.c @@ -33,10 +33,11 @@ #include "sqsh_expand.h" #include "sqsh_strchr.h" #include "sqsh_sig.h" +#include "sqsh_readline.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_expand.c,v 1.5 2010/01/26 15:03:50 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: sqsh_expand.c,v 1.9 2014/03/16 13:19:17 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -53,6 +54,9 @@ static int expand_command _ANSI_ARGS(( char**, char*, varbuf_t*, int )); static int expand_skip_eol _ANSI_ARGS(( char**, char*, varbuf_t*, int )); static int expand_skip_comment _ANSI_ARGS(( char**, char*, varbuf_t*, int )); static void expand_sighandler _ANSI_ARGS(( int, void* )); +#if defined (USE_READLINE) +static int expand_tilde _ANSI_ARGS(( char**, char*, char*, varbuf_t*, int )); +#endif int sqsh_expand( str, buf, flags ) char *str; @@ -70,7 +74,7 @@ int sqsh_expand( str, buf, flags ) * final results in buf. It attempts to follow some of the basic rules * of shells. If a variable is contained within double quotes it is still * expanded (although, unlike a shell it doesn't strip the quotes), if a - * variable is contained in double quotes it is not expanded. sqsh_expand() + * variable is contained in single quotes it is not expanded. sqsh_expand() * returns True upon success, and False if there is some sort of error. */ int sqsh_nexpand( str, buf, flags, n ) @@ -79,13 +83,15 @@ int sqsh_nexpand( str, buf, flags, n ) int flags; int n; { - int quote_type = QUOTE_NONE ; /* Which quotes are we in? */ - int r ; /* Results of varbuf_() functions */ + int quote_type = QUOTE_NONE ; /* Which type of quotes are we in? */ + int r ; /* Results of varbuf_() functions */ + char *str_start; /* Keep pointer to start of string */ char *str_end; int leading_whitespace = True; DBG(char *instr;) DBG(instr = str;) + str_start = str; /*-- Clear out the expansion buffer --*/ varbuf_clear( buf ); @@ -140,8 +146,7 @@ int sqsh_nexpand( str, buf, flags, n ) } else { - r = varbuf_charcat( buf, *str ); - ++str; + r = varbuf_charcat( buf, *str++ ); } break; @@ -153,8 +158,7 @@ int sqsh_nexpand( str, buf, flags, n ) } else { - r = varbuf_charcat( buf, *str ); - ++str; + r = varbuf_charcat( buf, *str++ ); } break; @@ -173,7 +177,7 @@ int sqsh_nexpand( str, buf, flags, n ) /* * Determine if we are contained within single quotes. If we - * are then paramters no longer get expanded. + * are then parameters no longer get expanded. */ case '\'': /* @@ -183,23 +187,24 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_DOUBLE) { r = varbuf_charcat( buf, *str++ ); - break; } - - /* - * Unless requested to do otherwise, go ahead and stick - * the quote in the destination buffer. - */ - if (!(flags & EXP_STRIPQUOTE)) - r = varbuf_charcat( buf, *str ); - - /* - * If we are in already in single quotes, then mark outselves - * as no longer being in them. Otherwise, we are currently - * in single quotes. - */ - quote_type = (quote_type==QUOTE_SINGLE)?QUOTE_NONE:QUOTE_SINGLE; - ++str; + else + { + /* + * Unless requested to do otherwise, go ahead and stick + * the quote in the destination buffer. + */ + if (!(flags & EXP_STRIPQUOTE)) + r = varbuf_charcat( buf, *str ); + + /* + * If we are already in single quotes, then mark ourselves + * as no longer being in them. Otherwise, we are currently + * in single quotes. + */ + quote_type = (quote_type==QUOTE_SINGLE)?QUOTE_NONE:QUOTE_SINGLE; + ++str; + } break; /* @@ -214,25 +219,26 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_SINGLE) { r = varbuf_charcat( buf, *str++ ); - break; } - - /* - * Unless requested to do otherwise, go ahead and stick - * the quote in the destination buffer. - */ - if (!(flags & EXP_STRIPQUOTE)) - r = varbuf_charcat( buf, *str ); - - /* - * If we are in already in double quotes, then mark outselves - * as no longer being in them. Otherwise, we are currently - * in double quotes. - */ - quote_type = (quote_type==QUOTE_DOUBLE)?QUOTE_NONE:QUOTE_DOUBLE; - ++str; + else + { + /* + * Unless requested to do otherwise, go ahead and stick + * the quote in the destination buffer. + */ + if (!(flags & EXP_STRIPQUOTE)) + r = varbuf_charcat( buf, *str ); + + /* + * If we are already in double quotes, then mark ourselves + * as no longer being in them. Otherwise, we are currently + * in double quotes. + */ + quote_type = (quote_type==QUOTE_DOUBLE)?QUOTE_NONE:QUOTE_DOUBLE; + ++str; + } break; - + /* * Look for the command substitution character. */ @@ -246,11 +252,12 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_SINGLE || flags & EXP_IGNORECMD) { r = varbuf_charcat( buf, *str++ ); - break; } - - if (expand_command( &str, str_end, buf, flags ) == False) - return False; + else + { + if (expand_command( &str, str_end, buf, flags ) == False) + return False; + } break; /* @@ -266,11 +273,12 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_SINGLE) { r = varbuf_charcat( buf, *str++ ); - break; } - - if (expand_escape( &str, str_end, buf, flags ) == False) - return False; + else + { + if (expand_escape( &str, str_end, buf, flags ) == False) + return False; + } break; /* @@ -286,11 +294,12 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_SINGLE) { r = varbuf_charcat( buf, *str++ ); - break; } - - if (expand_variable( &str, str_end, buf, flags ) == False) - return False; + else + { + if (expand_variable( &str, str_end, buf, flags ) == False) + return False; + } break; case '#': @@ -301,28 +310,45 @@ int sqsh_nexpand( str, buf, flags, n ) if (quote_type == QUOTE_SINGLE) { r = varbuf_charcat( buf, *str++ ); - break; } + else + { + /* + ** Only expand columns when there are actually + ** columns available to be expanded (this may + ** protect us against expanding weird temp-table + ** names. + */ + if ((flags & EXP_COLUMNS) != 0 && g_do_ncols > 0) + { + r = 0; + if (expand_column( &str, str_end, buf, flags ) == False) + return False; + } + else + { + r = varbuf_charcat( buf, *str++ ); + } + } + break; +#if defined (USE_READLINE) /* - ** Only expand columns when there are actually - ** columns available to be expanded (this may - ** protect us against expanding weird temp-table - ** names. + ** sqsh-2.5: Expand a tilde on the command line to the + ** corresponding home directory of the specified unix/linux login. */ - if ((flags & EXP_COLUMNS) != 0 && g_do_ncols > 0) + case '~': + if (quote_type == QUOTE_SINGLE || (flags & EXP_TILDE) == 0) { - r = 0; - if (expand_column( &str, str_end, buf, flags ) == False) - return False; + r = varbuf_charcat( buf, *str++ ); } else { - r = varbuf_charcat( buf, *str++ ); + if (expand_tilde( &str, str_start, str_end, buf, flags ) == False) + return False; } break; - - +#endif default: r = varbuf_charcat( buf, *str++ ); } @@ -350,7 +376,7 @@ int sqsh_nexpand( str, buf, flags, n ) /* * expand_skip_eol(): * - * Copy everything up to the current end of line into the + * Copy everything up to the current end of line into the * expand buffer. */ static int expand_skip_eol( cpp, str_end, buf, flags ) @@ -400,7 +426,7 @@ static int expand_skip_comment( cpp, str_end, buf, flags ) /* * Track down the end of comment. */ - while (*str && (str_end == NULL || str != (str_end-1)) && + while (*str && (str_end == NULL || str != (str_end-1)) && (*str != '*' || *(str+1) != '/')) { ++str; @@ -408,18 +434,18 @@ static int expand_skip_comment( cpp, str_end, buf, flags ) /* if we're not at the end of the string (CR 1046570)*/ if(*str) { - /* - * If we failed to find a closing comment, then - * we stopped at the end of line. - */ - if (*str != '*' || *(str+1) != '/') - { - ++str; - } - else - { - str += 2; - } + /* + * If we failed to find a closing comment, then + * we stopped at the end of line. + */ + if (*str != '*' || *(str+1) != '/') + { + ++str; + } + else + { + str += 2; + } } varbuf_strncat( buf, *cpp, str - (*cpp) ); @@ -436,7 +462,7 @@ static int expand_skip_comment( cpp, str_end, buf, flags ) * buffer (str_end), which may be NULL if the string is NULL terminated, * a desination buffer (buf), and the current set of parsing flags. cpp * should be pointing a ` character. - * + * */ static int expand_command( cpp, str_end, buf, flags ) char **cpp; @@ -480,7 +506,7 @@ static int expand_command( cpp, str_end, buf, flags ) sqsh_set_error( SQSH_E_BADQUOTE, "Unbounded ` character" ); return False; } - + /* * Create a buffer to hold the soon-to-be-expanded * command string. @@ -498,7 +524,7 @@ static int expand_command( cpp, str_end, buf, flags ) * may encounter along the way as well as any escape sequences * (so they may be interpreted by the underlying shell). */ - if (sqsh_nexpand( cmd_start, cmd, flags|EXP_STRIPNL|EXP_STRIPESC, + if (sqsh_nexpand( cmd_start, cmd, flags|EXP_STRIPNL|EXP_STRIPESC, (str - cmd_start) ) == False) { varbuf_destroy( cmd ); @@ -543,7 +569,7 @@ static int expand_command( cpp, str_end, buf, flags ) env_get( g_env, "ifs", &ifs ); if( ifs == NULL || *ifs == '\0' ) ifs = "\f\n\r\t\v"; - + /* * Because this expansion could theoretically take a while * we want to protect ourselves agains recieving an interrupt @@ -584,7 +610,7 @@ static int expand_command( cpp, str_end, buf, flags ) if( got_signal == 0 && ch != EOF ) varbuf_charcat( buf, ' ' ); } - + /* * While we haven't reached EOF, and we haven't hit an IFS * character start copying character into the buffer. @@ -677,7 +703,7 @@ static int expand_variable( cpp, str_end, buf, flags ) * the variable. We are still in part of the name if we * see the characters [?a-zA-Z0-9_] and special character # and *. */ - while (!(str_end == NULL && str == str_end) && *str != '\0' && + while (!(str_end == NULL && str == str_end) && *str != '\0' && (isalnum((int)*str) || strchr("#*?_$", *str) )) { if (!isdigit((int)*str)) @@ -689,7 +715,7 @@ static int expand_variable( cpp, str_end, buf, flags ) /* * Keep track of where the variable ends, this may not be - * equal to the value of str if the next character is a + * equal to the value of str if the next character is a * close brace. */ var_name_end = str; @@ -717,15 +743,41 @@ static int expand_variable( cpp, str_end, buf, flags ) if( var_name_start == var_name_end ) { - if (varbuf_charcat( buf, *str++ ) == -1) - return False; - *cpp = str; - return True; + if (varbuf_charcat( buf, *str++ ) == -1) + return False; + *cpp = str; + return True; } + /* - * Check for special case. First, $# is the number of arguments. + * Check for special cases. + * sqsh-2.2.0 - First, $? is the result of last action. */ - if (*var_name_start == '#' && + 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); + } + + /* + * Next, $# is the number of arguments. + */ + if (*var_name_start == '#' && (var_name_end - var_name_start) == 1) { /* @@ -745,23 +797,10 @@ 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", getpid() ); - varbuf_strcat( buf, nbr ); - *cpp = str; - return(True); - } - /* * Next, $* is the complete list of arguments. */ - if (*var_name_start == '*' && + if (*var_name_start == '*' && (var_name_end - var_name_start) == 1) { if (g_func_nargs > 0) @@ -780,7 +819,7 @@ static int expand_variable( cpp, str_end, buf, flags ) } /* - * Next special case. All digits point us to a function + * Next special case. All digits point us to a function * argument. */ if (all_digits == True) @@ -796,7 +835,7 @@ static int expand_variable( cpp, str_end, buf, flags ) /* * If invalid argument number, then just leave blank. */ - if (g_func_nargs == 0 || arg_nbr < 0 || + if (g_func_nargs == 0 || arg_nbr < 0 || arg_nbr > g_func_args[g_func_nargs-1].argc - 1) { *cpp = str; @@ -812,7 +851,7 @@ static int expand_variable( cpp, str_end, buf, flags ) * First, check to see if the variable is available in our * "external" environment. */ - r = env_nget( g_env, var_name_start, &var_value, + r = env_nget( g_env, var_name_start, &var_value, var_name_end - var_name_start); if (r == -1) @@ -843,7 +882,7 @@ static int expand_variable( cpp, str_end, buf, flags ) if( varbuf_strcat( buf, var_value ) == -1 ) return False; } - + *cpp = str; return True; } @@ -960,7 +999,7 @@ static int expand_escape( cpp, str_end, buf, flags ) if( varbuf_strncat( buf, str, 2 ) == -1 ) return False; } - + /* * Skip straight to the escaped character. */ @@ -975,7 +1014,7 @@ static int expand_escape( cpp, str_end, buf, flags ) *str != '\0' && *str != '\n' ) { if( varbuf_charcat( buf, *str ) == -1 ) return False; - } + } ++str; *cpp = str; @@ -995,6 +1034,75 @@ static void expand_sighandler( sig, user_data ) *((int*)user_data) = sig; } +#if defined (USE_READLINE) +/* + * expand_tilde(): + * + * sqsh-2.5 : New function to expand a tilde expression to the + * corresponding unix/linux login home directory. Only available + * if Readline support is included. + */ +static int expand_tilde( cpp, str_start, str_end, buf, flags ) + char **cpp; + char *str_start; + char *str_end; + varbuf_t *buf; + int flags; +{ + const char tilde_prefix[] = { ' ', '\"', '=', ':', '>', '<', '\t' }; + const char tilde_suffix[] = { ' ', '/', '\"', '=', ':', '\n', '\t', '\0' }; + char *str; + char *sqsh_tilde_expand; + char *tilde_name; + char *j; + int idx; + int found_prefix; + int found_suffix; + + str = *cpp; + + /* + * To be able to successfully expand a tilde directive like ~ or ~sybase, + * the tilde must be preceded with a character from the tilde_prefix list + * and the directive must be appended with a character from the tilde_suffix + * list. If all is well, we pass on the tilde directive to the Readline + * tilde_expand() function and store the result in the target buffer. + */ + found_prefix = found_suffix = False; + if (str == str_start) + found_prefix = True; /* ~ is the very first character of the string */ + else + { + for ( idx = 0; idx < sizeof(tilde_prefix) && !found_prefix; ++idx ) + if (*(str-1) == tilde_prefix[idx]) + found_prefix = True; + } + for ( j = str+1; isalnum((int) *j); j++ ); + for ( idx = 0; idx < sizeof(tilde_suffix) && !found_suffix; ++idx) + if (*j == tilde_suffix[idx]) + found_suffix = True; + + if (found_prefix && found_suffix) + { + if ((tilde_name = malloc ( (int) (j - str + 1))) == NULL) + return False; + strncpy ( tilde_name, str, j - str ); + tilde_name[j-str] = '\0'; + sqsh_tilde_expand = tilde_expand ( tilde_name ); + varbuf_strcat( buf, sqsh_tilde_expand ); + free ( sqsh_tilde_expand ); + free ( tilde_name ); + str = j; + } + else + { + varbuf_charcat( buf, *str++ ); + } + + *cpp = str; + return True; +} +#endif /* * sqsh-2.1.6 feature - expand_color_prompt() diff --git a/src/sqsh_expand.h b/src/sqsh_expand.h index a566345..ceb908d 100644 --- a/src/sqsh_expand.h +++ b/src/sqsh_expand.h @@ -35,7 +35,8 @@ #define EXP_STRIPNL (1<<2) /* Strip out newlines */ #define EXP_IGNORECMD (1<<3) /* Ignore command substitution */ #define EXP_COMMENT (1<<4) /* Pay attention to comments */ -#define EXP_COLUMNS (1<<5) /* Pay attention to comments */ +#define EXP_COLUMNS (1<<5) /* Pay attention to columns */ +#define EXP_TILDE (1<<6) /* sqsh-2.5: Pay attention to tildes */ /* * Passing a positive value into sqsh_nexpand() causes it to expand until diff --git a/src/sqsh_getopt.c b/src/sqsh_getopt.c index 6d93d5c..0b5afe9 100644 --- a/src/sqsh_getopt.c +++ b/src/sqsh_getopt.c @@ -33,7 +33,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_getopt.c,v 1.3 2008/04/06 10:03:08 mpeppler Exp $" ; +static char RCS_Id[] = "$Id: sqsh_getopt.c,v 1.4 2013/02/24 22:21:10 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -366,7 +366,8 @@ int sqsh_getopt_env( var_name, opt_flags ) /*-- Arguments must begin with a '-' --*/ if( *var_value != '-' ) { - sqsh_set_error( SQSH_E_BADPARAM, "Options must begin with '-'" ) ; + sqsh_set_error( SQSH_E_BADPARAM, "Options must begin with '-' (found: %s)", + var_value ) ; goto leave_err ; } @@ -394,8 +395,7 @@ int sqsh_getopt_env( var_name, opt_flags ) * Check to see if the next thing on the line is either EOF * or another argument. */ - if( *var_value == '\0' || isspace((int)*var_value) || - is_flag(var_value) ) { + if( *var_value == '\0' || is_flag(var_value) ) { /* * If this option requires an argument and there isn't one * available, then spew an error message. @@ -431,7 +431,6 @@ int sqsh_getopt_env( var_name, opt_flags ) /* * The option doesn't take an argument, so simply return. */ - ++var_value ; sqsh_optarg = NULL ; return flag ; diff --git a/src/sqsh_global.c b/src/sqsh_global.c index 5bfd1e3..3c6db63 100644 --- a/src/sqsh_global.c +++ b/src/sqsh_global.c @@ -28,7 +28,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_global.c,v 1.6 2010/01/26 15:03:50 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_global.c,v 1.11 2014/01/19 10:26:00 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -50,10 +50,23 @@ alias_t *g_alias = NULL; char *g_password = NULL; int g_password_set = False; char *g_lock = NULL; -char *g_copyright = "Copyright (C) 1995-2001 Scott C. Gray\nPortions Copyright (C) 2004-2010 Michael Peppler"; +char *g_copyright = "Copyright (C) 1995-2001 Scott C. Gray\nPortions Copyright (C) 2004-2014 Michael Peppler and Martin Wesdorp"; char *g_version = SQSH_VERSION; dsp_desc_t *g_do_cols[64]; int g_do_ncols = 0; funcarg_t g_func_args[64]; -int g_func_nargs = 0; -int g_interactive = False; +int g_func_nargs = 0; +int g_interactive = False; + +#if defined(HAVE_LOCALE_H) + struct lconv *g_lconv = NULL; +#else + void *g_lconv = NULL; +#endif + +/* + * sqsh-2.5 - Initialize variables for p2f feature. + */ +FILE *g_p2f_fp = NULL; +int g_p2fc = 0; + diff --git a/src/sqsh_global.h b/src/sqsh_global.h index 2dc101a..4d5b978 100644 --- a/src/sqsh_global.h +++ b/src/sqsh_global.h @@ -35,6 +35,12 @@ #include "dsp.h" #include "sqsh_func.h" +#include "config.h" + +#if defined(HAVE_LOCALE_H) + #include <locale.h> +#endif + /* g_cs_ver: This is the value of CS_VERSION_xxx. Stored in a global * because it is needed to figure out the correct BLK_VERSION_xxx * value to use in cmd_blk.c @@ -141,7 +147,7 @@ extern char *g_version ; /* * g_password & g_lock: Contains the current value of the regular database - * password and the session lock password. + * password and the session lock password. */ extern int g_password_set; extern char *g_password; @@ -152,4 +158,20 @@ extern char *g_lock; */ extern int g_interactive; +/* + * g_lconv: sqsh-2.3 - Do locale conversion of numeric/decimal/money datatypes. + */ +#if defined(HAVE_LOCALE_H) + extern struct lconv *g_lconv; +#else + extern void *g_lconv; +#endif + +/* + * sqsh-2.5 - New feature: Print to file from message handler after $p2faxm + * number of printed messages to screen. + */ +extern FILE *g_p2f_fp; /* Print to file filepointer */ +extern int g_p2fc; /* Print to file count */ + #endif diff --git a/src/sqsh_history.c b/src/sqsh_history.c index 2998eb5..0a54c97 100644 --- a/src/sqsh_history.c +++ b/src/sqsh_history.c @@ -23,15 +23,17 @@ * gray@xenotropic.com */ #include <stdio.h> +#include <sys/stat.h> #include "sqsh_config.h" #include "sqsh_error.h" +#include "sqsh_expand.h" +#include "sqsh_global.h" #include "sqsh_history.h" #include "sqsh_varbuf.h" -#include "sqsh_global.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_history.c,v 1.6 2010/01/28 15:30:37 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_history.c,v 1.10 2013/05/03 11:19:38 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -42,6 +44,7 @@ static int hisbuf_destroy _ANSI_ARGS(( hisbuf_t* )) ; static unsigned long adler32 _ANSI_ARGS(( char*, int )) ; /* sqsh-2.1.6 feature */ static int chk_buf_ifs _ANSI_ARGS(( char*, int )) ; /* sqsh-2.1.7 feature */ static void hist_auto_save _ANSI_ARGS(( history_t* )) ; /* sqsh-2.1.7 feature */ +static int history_merge _ANSI_ARGS(( history_t*, history_t*)) ; /* sqsh-2.2.0 feature */ /* @@ -216,7 +219,7 @@ int history_append( h, buf ) * order; else continue as usual. */ chksum = adler32 (buf, len); - DBG(sqsh_debug(DEBUG_ERROR, "sqsh_history: checksum of buffer: %u\n", chksum);) + DBG(sqsh_debug(DEBUG_HISTORY, "sqsh_history: checksum of buffer: %u\n", chksum);) env_get (g_env, "histunique", &histunique); if (histunique != NULL && *histunique != '0') { @@ -411,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 ; @@ -446,7 +450,7 @@ int history_range_del( h, idx_start, idx_end ) h->h_end = hb->hb_prv ; hisbuf_destroy( hb ) ; - h->h_nitems--; + h->h_nitems--; } /* @@ -510,9 +514,12 @@ int history_save( h, save_file ) history_t *h ; char *save_file ; { - hisbuf_t *hb ; - FILE *fptr ; - int saved_mask; + hisbuf_t *hb ; + FILE *fptr ; + mode_t saved_mask; + char *histmerge; + history_t *x; + /*-- Check the arguments --*/ if( h == NULL || save_file == NULL ) { @@ -520,9 +527,25 @@ int history_save( h, save_file ) return False ; } - /*-- Open the file to be save to --*/ + /* + * 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' && + h->h_change != HISTSAVE_FORCE) + { + x = history_create (history_get_size(h)); + if (history_load (x, save_file) == True) + history_merge (h, x); + history_destroy (x); + } + + /*-- Open the file to save to --*/ /* fix for 1105398 */ - saved_mask = umask(0066); + saved_mask = umask( (mode_t) 0066); if( (fptr = fopen( save_file, "w" )) == NULL ) { sqsh_set_error( errno, "%s: %s", save_file, strerror( errno ) ) ; umask(saved_mask); @@ -877,7 +900,7 @@ static void hist_auto_save ( h ) histsave == NULL || *histsave == '0') return; - if ( h->h_change != HISTSAVE_FORCE && + if ( h->h_change != HISTSAVE_FORCE && ++h->h_change < atoi(hist_auto_save) ) return; @@ -891,7 +914,7 @@ static void hist_auto_save ( h ) if ( sqsh_expand( history, exp_buf, 0 ) == True ) { history_save( h, varbuf_getstr(exp_buf) ); - DBG(sqsh_debug(DEBUG_ERROR, "sqsh_history: History automatically saved to %s\n", + DBG(sqsh_debug(DEBUG_HISTORY, "sqsh_history: History automatically saved to %s\n", varbuf_getstr(exp_buf));) } varbuf_destroy( exp_buf ); @@ -900,3 +923,196 @@ static void hist_auto_save ( h ) return; } + +/* + * history_merge(): + * + * sqsh-2.2.0 - Merge the history list of x into the history list of h. + */ +static int history_merge (h, x) + history_t *h; + history_t *x; +{ + hisbuf_t *hbh; + hisbuf_t *hbx; + hisbuf_t *hbt; + int i; + char *histunique; +#if defined (DEBUG) + char hdrinfo[64]; + char *line, *nl; +#endif + + + if (h == NULL || x == NULL) + { + sqsh_set_error( SQSH_E_BADPARAM, NULL ) ; + return False; + } + + /* + * if histunique=On then remove the oldest double entries + * (based on hb_chksum) from h or x, otherwise only remove + * double entries from x, regardless the values of hb_dttm. + * Kind of nested loop join, h is outer table, x is inner table. + */ + env_get (g_env, "histunique", &histunique); + hbh = h->h_start; + hbx = x->h_start; + while (hbh != NULL && hbx != NULL) + { + if (hbh->hb_chksum == hbx->hb_chksum) + { + if (hbx->hb_dttm > hbh->hb_dttm && *histunique == '1') + { + hbt = hbh->hb_nxt; + if (hbh->hb_prv != NULL) + hbh->hb_prv->hb_nxt = hbh->hb_nxt; + else + h->h_start = hbh->hb_nxt; + if (hbh->hb_nxt != NULL) + hbh->hb_nxt->hb_prv = hbh->hb_prv; + else + h->h_end = hbh->hb_prv; + hisbuf_destroy (hbh); + h->h_nitems--; + hbh = hbt; + hbx = x->h_start; + } + else + { + hbt = hbx->hb_nxt; + if (hbx->hb_prv != NULL) + hbx->hb_prv->hb_nxt = hbx->hb_nxt; + else + x->h_start = hbx->hb_nxt; + if (hbx->hb_nxt != NULL) + hbx->hb_nxt->hb_prv = hbx->hb_prv; + else + x->h_end = hbx->hb_prv; + hisbuf_destroy (hbx); + x->h_nitems--; + if ((hbx = hbt) == NULL) + { + hbh = hbh->hb_nxt; + hbx = x->h_start; + } + } + } + else + { + if ((hbx = hbx->hb_nxt) == NULL) + { + hbh = hbh->hb_nxt; + hbx = x->h_start; + } + } + } + +#if defined (DEBUG) + if ( sqsh_debug_show (DEBUG_HISTORY) ) + { + fprintf (stdout, "history_merge: Available entries in original list %d\n", h->h_nitems); + fprintf (stdout, "history_merge: Available entries in merge list %d\n", x->h_nitems); + for (hbx = x->h_end; hbx != NULL; hbx = hbx->hb_prv) + { + line = hbx->hb_buf; + while ((nl = strchr (line, '\n' )) != NULL) + { + if (line == hbx->hb_buf) { + sprintf (hdrinfo, "(%d) ", hbx->hb_nbr); + fprintf (stdout, "%s%*.*s\n", hdrinfo, (int) (nl - line), (int) (nl - line), line); + } else { + fprintf (stdout, "%*s%*.*s\n", (int) strlen (hdrinfo), " ", (int) (nl - line), (int) (nl - line), line); + } + line = nl + 1; + } + if ( *line != '\0' ) + fprintf (stdout, " %s\n", line); + } + } +#endif + + /* + * The remaining entries of x should be relinked into h + * order by hb_dttm. + */ + for (hbx = x->h_start; hbx != NULL; hbx = x->h_start) + { + /* + * Unlink the first node from x. + */ + x->h_start = hbx->hb_nxt; + if (hbx->hb_nxt != NULL) + hbx->hb_nxt->hb_prv = NULL; + else + x->h_end = NULL; + x->h_nitems--; + + /* + * Link this node into h based on value of dttm in MRU-LRU order. + */ + for (hbh = h->h_start; hbh != NULL && hbh->hb_dttm > hbx->hb_dttm; hbh = hbh->hb_nxt); + + if (hbh != NULL) + { + if (hbh->hb_prv != NULL) + hbh->hb_prv->hb_nxt = hbx; + else + h->h_start = hbx; + hbx->hb_nxt = hbh; + hbx->hb_prv = hbh->hb_prv; + hbh->hb_prv = hbx; + } + else + { + if (h->h_end != NULL) + h->h_end->hb_nxt = hbx; + else + h->h_start = hbx; + hbx->hb_prv = h->h_end; + h->h_end = hbx; + hbx->hb_nxt = NULL; + } + ++h->h_nitems; + } + + /* + * Renumber the list. + */ + switch (h->h_nitems) + { + case 0 : + h->h_next_nbr = 1; + break; + case 1 : + h->h_start->hb_nbr = 1; + h->h_next_nbr = 2; + break; + default : + for (hbh = h->h_start, i = h->h_nitems, h->h_next_nbr = i + 1; + hbh != NULL; hbh->hb_nbr = i--, hbh = hbh->hb_nxt); + break; + } + + /* + * If there are more entries than the allowed size of the list then + * unlink the oldest entries from the list and destroy them. + */ + while (h->h_size < h->h_nitems) + { + hbh = h->h_end; + if (hbh->hb_prv != NULL) + { + h->h_end = hbh->hb_prv; + h->h_end->hb_nxt = NULL; + } + else + h->h_end = h->h_start = NULL; + hisbuf_destroy (hbh); + --h->h_nitems; + } + + return True; +} + diff --git a/src/sqsh_init.c b/src/sqsh_init.c index 2619036..68613f7 100644 --- a/src/sqsh_init.c +++ b/src/sqsh_init.c @@ -32,6 +32,10 @@ #include "sqsh_readline.h" #include "sqsh_stdin.h" #include "sqsh_init.h" +#include "config.h" +#if defined(HAVE_LOCALE_H) +#include <locale.h> +#endif /* * The following defines the tables which are used to inialize the * variable global variables. @@ -44,7 +48,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_init.c,v 1.3 2010/02/17 11:35:06 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_init.c,v 1.9 2013/12/03 09:22:23 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -64,8 +68,16 @@ int sqsh_init() char *histsize ; varbuf_t *expand_buf ; + + /* + * sqsh-2.3 : Initialize locale to the default of C. + */ +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) + setlocale ( LC_ALL, "" ); +#endif + /* - * g_connection: This variable is initiazed to NULL. It is the responsibility + * g_connection: This variable is initiazed to NULL. It is the responsibility * of a user function to actually perform the connection to * set it. This allows sqsh to be started without actually * connecting to the database. @@ -79,7 +91,6 @@ int sqsh_init() */ if( (g_sqlbuf = varbuf_create( 1024 )) == NULL ) { sqsh_set_error( sqsh_get_error(), "varbuf_create: %s", sqsh_get_errstr()); - varbuf_destroy( g_sqlbuf ) ; return False ; } @@ -98,7 +109,7 @@ int sqsh_init() */ if ((g_funcset = funcset_create()) == NULL) { - sqsh_set_error( sqsh_get_error(), + sqsh_set_error( sqsh_get_error(), "cmdset_create: %s", sqsh_get_errstr()); return False; } @@ -109,7 +120,7 @@ int sqsh_init() */ for( i = 0; i < (sizeof(sg_cmd_entry) / sizeof(cmd_entry_t)); i++ ) { - if( cmdset_add( g_cmdset, + if( cmdset_add( g_cmdset, sg_cmd_entry[i].ce_name, sg_cmd_entry[i].ce_func ) == False ) { sqsh_set_error( sqsh_get_error(), "cmdset_add: %s", @@ -128,7 +139,7 @@ int sqsh_init() } for( i = 0; i < (sizeof(sg_alias_entry) / sizeof(alias_entry_t)); i++ ) { - if( alias_add( g_alias, + if( alias_add( g_alias, sg_alias_entry[i].ae_name, sg_alias_entry[i].ae_body ) == False ) { sqsh_set_error( sqsh_get_error(), "alias_add: %s: %s", @@ -188,9 +199,9 @@ int sqsh_init() * environment. This, more-or-less, emulates the behaviour as * if you had typed it in from the command line. */ - if( sqsh_expand( sg_var_entry[i].ve_value, expand_buf, + if( sqsh_expand( sg_var_entry[i].ve_value, expand_buf, EXP_STRIPESC ) == False ){ - sqsh_set_error( sqsh_get_error(), "%s: %s", + sqsh_set_error( sqsh_get_error(), "%s: %s", sg_var_entry[i].ve_value, sqsh_get_errstr()); return False ; } @@ -201,7 +212,7 @@ int sqsh_init() varbuf_getstr(expand_buf), /* Default value */ sg_var_entry[i].ve_set, /* Settor function */ sg_var_entry[i].ve_get ) == False ) { - sqsh_set_error( sqsh_get_error(), "env_set_valid: %s", + sqsh_set_error( sqsh_get_error(), "env_set_valid: %s", sqsh_get_errstr() ) ; return False ; } @@ -212,7 +223,7 @@ int sqsh_init() NULL, /* NULL value */ sg_var_entry[i].ve_set, /* Settor function */ sg_var_entry[i].ve_get ) == False ) { - sqsh_set_error( sqsh_get_error(), "env_set_valid: %s", + sqsh_set_error( sqsh_get_error(), "env_set_valid: %s", sqsh_get_errstr() ) ; return False ; } @@ -223,10 +234,16 @@ 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 ) { - sqsh_set_error( sqsh_get_error(), "jobset_create: %s", + sqsh_set_error( sqsh_get_error(), "jobset_create: %s", sqsh_get_errstr() ) ; return False ; } @@ -241,7 +258,7 @@ int sqsh_init() i = 10 ; if( (g_history = history_create( i )) == NULL ) { - sqsh_set_error( sqsh_get_error(), "history_create: %s", + sqsh_set_error( sqsh_get_error(), "history_create: %s", sqsh_get_errstr() ) ; return False ; } @@ -312,14 +329,16 @@ void sqsh_exit( exit_status ) if( g_connection != NULL ) { - ct_close( g_connection, CS_FORCE_CLOSE ); + if (ct_close( g_connection, CS_UNUSED) != CS_SUCCEED) + ct_close( g_connection, CS_FORCE_CLOSE ); ct_con_drop( g_connection ); g_connection = NULL; } if (g_context != NULL) { - ct_exit( g_context, CS_FORCE_EXIT ); + if (ct_exit( g_context, CS_UNUSED ) != CS_SUCCEED) + ct_exit( g_context, CS_FORCE_EXIT ); /* * If sqsh is aborting, maybe because of losing a database connection @@ -333,7 +352,7 @@ void sqsh_exit( exit_status ) * This is due to the fact that the callback handler did not return * to CS/CT-Library. */ - if (exit_status != 254) + if (exit_status != 254) cs_ctx_drop( g_context ); g_context = NULL; } @@ -343,6 +362,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. */ @@ -353,6 +377,14 @@ void sqsh_exit( exit_status ) fprintf (stdout, "%c]0;%c", '\033', '\007' ); } + /* + * sqsh-2.5 - Close file $p2fname + */ + if (g_p2f_fp != NULL) { + fclose (g_p2f_fp); + g_p2f_fp = NULL; + } + if( g_env != NULL ) { env_destroy( g_env ) ; g_env = NULL; diff --git a/src/sqsh_job.c b/src/sqsh_job.c index a25c3d7..ee747d0 100644 --- a/src/sqsh_job.c +++ b/src/sqsh_job.c @@ -29,6 +29,7 @@ #include "sqsh_config.h" #include "sqsh_error.h" #include "sqsh_fd.h" +#include "sqsh_init.h" #include "sqsh_tok.h" #include "sqsh_cmd.h" #include "sqsh_global.h" @@ -42,7 +43,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_job.c,v 1.4 2010/01/28 15:30:37 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: sqsh_job.c,v 1.11 2014/03/14 17:24:53 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -51,7 +52,7 @@ static job_t* job_alloc _ANSI_ARGS((jobset_t*)); static int job_free _ANSI_ARGS((job_t*)); static job_id_t jobset_wait_all _ANSI_ARGS((jobset_t*, int*, int)); static int jobset_parse _ANSI_ARGS((jobset_t*, job_t*, char*, - varbuf_t*, int)); + varbuf_t*, int)); static job_t* jobset_get _ANSI_ARGS((jobset_t*, job_id_t)); static void jobset_run_sigint _ANSI_ARGS((int, void*)); static int jobset_get_cmd _ANSI_ARGS((jobset_t*, char*, cmd_t**)); @@ -118,9 +119,8 @@ jobset_t* jobset_create( hsize ) if( (js->js_sigcld = sigcld_create()) == NULL ) { free( js->js_jobs ); free( js ); - sqsh_set_error( sqsh_get_error(), "sigcld_create: %s", - sqsh_get_errstr() ); - return NULL; + sqsh_set_error( sqsh_get_error(), "sigcld_create: %s", sqsh_get_errstr() ); + return NULL; } /*-- Initialize our command structure --*/ @@ -183,14 +183,14 @@ static int jobset_get_cmd( js, cmd_line, cmd ) return 0; DBG(sqsh_debug( DEBUG_JOB, "jobset_get_cmd: Testing '%s'\n", - varbuf_getstr(sg_cmd_buf) );) + varbuf_getstr(sg_cmd_buf) );) /* * Try to grab the first token from the command line. If there * is any error while tokenizing, then we will assume that this * isn't a command. */ - if( sqsh_tok( varbuf_getstr( sg_cmd_buf ), &tok, 0 ) == False ) + if( sqsh_tok( varbuf_getstr( sg_cmd_buf ), &tok, 0 ) == False ) return 0; /* @@ -200,7 +200,7 @@ static int jobset_get_cmd( js, cmd_line, cmd ) * command. */ if( tok->tok_type != SQSH_T_WORD || - (*cmd = cmdset_get(g_cmdset, sqsh_tok_value(tok))) == NULL ) + (*cmd = cmdset_get(g_cmdset, sqsh_tok_value(tok))) == NULL ) return 0; return 1; @@ -310,11 +310,11 @@ job_id_t jobset_run( js, cmd_line, exit_status ) * Expand the command line of any tokens, keeping quotes and stripping * escape characters (i.e. removing them as part of the expansion * process). + * sqsh-2.5 : Implemented tilde expansion in sqsh_expand(). */ - if (sqsh_expand( cmd_line, sg_cmd_buf, EXP_COLUMNS ) == False) + if (sqsh_expand( cmd_line, sg_cmd_buf, EXP_COLUMNS | EXP_TILDE ) == False) { - sqsh_set_error( sqsh_get_error(), "sqsh_expand: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_expand: %s", sqsh_get_errstr() ); return -1; } @@ -366,7 +366,7 @@ job_id_t jobset_run( js, cmd_line, exit_status ) /* * If this was a \while statement, then the sole argument to the - * function will be the unexpanted command line stripped of + * function will be the unexpanded command line stripped of * all redirection crap. */ if (while_buf != NULL) @@ -374,8 +374,7 @@ job_id_t jobset_run( js, cmd_line, exit_status ) if (args_add(job->job_args, "\\while" ) == False || args_add(job->job_args, varbuf_getstr(while_buf)) == False) { - sqsh_set_error( sqsh_get_error(), "args_add: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "args_add: %s", sqsh_get_errstr() ); goto jobset_abort; } } @@ -414,6 +413,7 @@ job_id_t jobset_run( js, cmd_line, exit_status ) */ while (sig_restore() >= 0); sig_install ( SIGINT, SIG_H_IGN, NULL, 0 ); + sqsh_getopt_reset(); ret = cmd->cmd_ptr( args_argc(job->job_args), args_argv(job->job_args) ); sqsh_exit(0); @@ -449,9 +449,9 @@ job_id_t jobset_run( js, cmd_line, exit_status ) /* * Link the new job into our hash table. */ - hval = job->job_id % js->js_hsize; - job->job_nxt = js->js_jobs[hval]; - js->js_jobs[hval] = job; + hval = job->job_id % js->js_hsize; + job->job_nxt = js->js_jobs[hval]; + js->js_jobs[hval] = job; /*-- And return it --*/ return job->job_id; @@ -484,14 +484,12 @@ job_id_t jobset_run( js, cmd_line, exit_status ) { sig_install( SIGPIPE, SIG_H_POLL, (void*)NULL, 0 ); - *exit_status = cmd->cmd_ptr( args_argc(job->job_args), - args_argv(job->job_args) ); + *exit_status = cmd->cmd_ptr( args_argc(job->job_args), args_argv(job->job_args) ); } else { - *exit_status = cmd->cmd_ptr( args_argc(job->job_args), - args_argv(job->job_args) ); + *exit_status = cmd->cmd_ptr( args_argc(job->job_args), args_argv(job->job_args) ); } } @@ -520,14 +518,14 @@ job_id_t jobset_run( js, cmd_line, exit_status ) * Lastly, destroy the job structure that we allocated. It almost * makes you wonder why it was created at all. */ - job_free( job ); + job_free( job ); /* * Note, reguardless of the exit status of the command, we return 0 * (i.e. the command was called succesfully reguarldess of whether * or not the job performed its task. */ - sqsh_set_error( SQSH_E_NONE, NULL ); + sqsh_set_error( SQSH_E_NONE, NULL ); return 0; jobset_abort: @@ -589,9 +587,7 @@ job_id_t jobset_wait( js, job_id, exit_status, block_type ) pid_t pid; /*-- Always check your parameters --*/ - if( js == NULL || exit_status == NULL || - (block_type != JOB_BLOCK && block_type != JOB_NONBLOCK) ) { - + if( js == NULL || exit_status == NULL || (block_type != JOB_BLOCK && block_type != JOB_NONBLOCK) ) { sqsh_set_error( SQSH_E_BADPARAM, NULL ); return -1; } @@ -602,7 +598,7 @@ job_id_t jobset_wait( js, job_id, exit_status, block_type ) /*-- Find out if the job exists --*/ /* (sqsh-2.1.7 - Bug fix for bucket calculation) --*/ for( j = js->js_jobs[job_id % js->js_hsize]; - j != NULL && j->job_id != job_id ; j = j->job_nxt ); + j != NULL && j->job_id != job_id ; j = j->job_nxt ); /*-- If we can't, error --*/ if( j == NULL ) { @@ -643,9 +639,9 @@ job_id_t jobset_wait( js, job_id, exit_status, block_type ) * If we have reached this point, then the job has completed so * it is just a matter of recording the exit status and returning. */ - j->job_flags |= JOB_DONE; + j->job_flags |= JOB_DONE; j->job_end = time(NULL); - j->job_status = *exit_status; + j->job_status = *exit_status; /* * Propagate any errors back to the caller. @@ -659,10 +655,10 @@ job_id_t jobset_wait( js, job_id, exit_status, block_type ) sqsh_set_error( sqsh_get_error(), "sigcld_wait: %s", sqsh_get_errstr() ); } else { - sqsh_set_error( SQSH_E_NONE, NULL ); + sqsh_set_error( SQSH_E_NONE, NULL ); } - return j->job_id; + return j->job_id; } int jobset_end( js, job_id ) @@ -685,8 +681,8 @@ int jobset_end( js, job_id ) /*-- Search for the job --*/ j_prv = NULL; for( j = js->js_jobs[hval]; j != NULL && j->job_id != job_id; - j = j->job_nxt ) - j_prv = j; + j = j->job_nxt ) + j_prv = j; if( j == NULL ) { sqsh_set_error( SQSH_E_EXIST, "Invalid job_id %d", job_id ); @@ -701,31 +697,28 @@ int jobset_end( js, job_id ) /*-- Kill the job --*/ if( kill( j->job_pid, SIGTERM ) == -1 ) { - sqsh_set_error( errno, "Unable to SIGTERM pid %d: %s", j->job_pid, - strerror( errno ) ); - return False; + sqsh_set_error( errno, "Unable to SIGTERM pid %d: %s", j->job_pid, strerror( errno ) ); + return False; } /*-- Wait for it to die. --*/ - if( sigcld_wait( js->js_sigcld, j->job_pid, &exit_status, - SIGCLD_BLOCK ) == -1 ) { - sqsh_set_error( sqsh_get_error(), "sigcld_wait: %s", - sqsh_get_errstr() ); - return False; + if( sigcld_wait( js->js_sigcld, j->job_pid, &exit_status, SIGCLD_BLOCK ) == -1 ) { + sqsh_set_error( sqsh_get_error(), "sigcld_wait: %s", sqsh_get_errstr() ); + return False; } } /* * Finally unlink it from the list of jobs that are running. */ - if( j_prv != NULL ) - j_prv->job_nxt = j->job_nxt; + if( j_prv != NULL ) + j_prv->job_nxt = j->job_nxt; else js->js_jobs[hval] = j->job_nxt; - job_free( j ); - sqsh_set_error( SQSH_E_NONE, NULL ); - return True; + job_free( j ); + sqsh_set_error( SQSH_E_NONE, NULL ); + return True; } @@ -866,8 +859,7 @@ int jobset_destroy( js ) * child process is going down. */ kill( j->job_pid, SIGTERM ); - sigcld_wait( js->js_sigcld, j->job_pid, &exit_status, - SIGCLD_BLOCK ); + sigcld_wait( js->js_sigcld, j->job_pid, &exit_status, SIGCLD_BLOCK ); } job_free( j ); @@ -928,7 +920,7 @@ static job_id_t jobset_wait_all( js, exit_status, block_type ) * then return 0. */ if( pid == 0 ) { - sqsh_set_error( SQSH_E_NONE, NULL ); + sqsh_set_error( SQSH_E_NONE, NULL ); return 0; } @@ -939,9 +931,9 @@ static job_id_t jobset_wait_all( js, exit_status, block_type ) for( i = 0; i < js->js_hsize; i++ ) { for( j = js->js_jobs[i]; j != NULL && j->job_pid != pid; - j = j->job_nxt ); + j = j->job_nxt ); - if( j != NULL ) { + if( j != NULL ) { /* * If we have reached this point, then the job has completed so @@ -961,8 +953,8 @@ static job_id_t jobset_wait_all( js, exit_status, block_type ) * for a pid that we don't have registered as belonging to a job. * Hmmm...what to do? */ - sqsh_set_error( SQSH_E_EXIST, "Received SIGCHLD for unknown pid!" ); - return -1; + sqsh_set_error( SQSH_E_EXIST, "Received SIGCHLD for unknown pid!" ); + return -1; } /* @@ -994,7 +986,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) char *pipe_ptr = NULL ; /* Location of | */ char *cp; /* sqsh-2.1.6 - New variables */ - varbuf_t *exp_buf; + varbuf_t *exp_buf = NULL ; /* @@ -1011,7 +1003,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) */ cp = cmd_line; while( (bg_ptr = sqsh_strchr( cp, '&' )) != NULL && - bg_ptr != cmd_line && *(bg_ptr - 1) == '>' ) + bg_ptr != cmd_line && *(bg_ptr - 1) == '>' ) cp = bg_ptr + 1; /* @@ -1053,11 +1045,10 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) if( tmp_dir == NULL || *tmp_dir == '\0' ) tmp_dir = SQSH_TMP; else /* sqsh-2.1.6 feature - Expand tmp_dir variable */ - { + { if ((exp_buf = varbuf_create( 512 )) == NULL) { - sqsh_set_error( sqsh_get_error(),"varbuf: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "varbuf: %s", sqsh_get_errstr() ); return False; } if (sqsh_expand( tmp_dir, exp_buf, 0 ) == False) @@ -1067,10 +1058,9 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) } /*-- Create the defer file --*/ - sprintf( defer_path, "%s/sqsh-dfr.%d-%d", - tmp_dir, (int) getpid(), job->job_id ); - - varbuf_destroy( exp_buf ); /* sqsh-2.1.6 feature */ + sprintf( defer_path, "%s/sqsh-dfr.%d-%d", tmp_dir, (int) getpid(), job->job_id ); + if ( exp_buf != NULL ) + varbuf_destroy( exp_buf ); /* sqsh-2.1.6 feature */ /*-- Let the job structure know where it is --*/ if( (job->job_output = sqsh_strdup( defer_path )) == NULL ) { @@ -1080,8 +1070,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) /*-- Now, open the file --*/ if( (defer_fd = sqsh_open(defer_path,O_CREAT|O_WRONLY|O_TRUNC,0600)) == -1 ) { - sqsh_set_error( sqsh_get_error(), "Unable to open %s: %s", - defer_path, sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "Unable to open %s: %s", defer_path, sqsh_get_errstr() ); return False; } @@ -1090,9 +1079,8 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * stdout and stderr. */ if( sqsh_dup2( defer_fd, fileno(stdout) ) == -1 || - sqsh_dup2( defer_fd, fileno(stderr) ) == -1 ) { - sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", - sqsh_get_errstr() ); + sqsh_dup2( defer_fd, fileno(stderr) ) == -1 ) { + sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", sqsh_get_errstr() ); sqsh_close( defer_fd ); return False; } @@ -1140,8 +1128,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) if( (fd = sqsh_popen( pipe_ptr+1, "w", NULL, NULL )) == -1 ) { env_set( g_internal_env, "?", "-255" ); - sqsh_set_error(sqsh_get_error(), "sqsh_popen: %s", - sqsh_get_errstr()); + sqsh_set_error( sqsh_get_error(), "sqsh_popen: %s", sqsh_get_errstr()); return False; } @@ -1150,8 +1137,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * created to our stdout. */ if( sqsh_dup2( fd, fileno(stdout) ) == -1 ) { - sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", sqsh_get_errstr() ); sqsh_close( fd ); return False; } @@ -1195,8 +1181,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * the file descriptor to. */ if( sqsh_tok( NULL, &tok, tok_flags ) == False ) { - sqsh_set_error( sqsh_get_error(), "sqsh_tok: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_tok: %s", sqsh_get_errstr() ); return False; } @@ -1219,9 +1204,9 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) flag = O_WRONLY | O_CREAT | O_TRUNC; /*-- Now, open the file --*/ - if( (fd = sqsh_open( sqsh_tok_value(tok), flag, 0 )) == -1 ) { - sqsh_set_error( sqsh_get_error(), "Unable to open %s: %s", - sqsh_tok_value(tok), sqsh_get_errstr() ); + cp = sqsh_tok_value(tok); + if( (fd = sqsh_open( cp, flag, 0 )) == -1 ) { + sqsh_set_error( sqsh_get_error(), "Unable to open %s: %s", cp, sqsh_get_errstr() ); return False; } @@ -1230,8 +1215,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * to the newly opened file and close the file. */ if( sqsh_dup2( fd, tok->tok_fd_left ) == -1 ) { - sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", sqsh_get_errstr() ); return False; } sqsh_close( fd ); @@ -1244,8 +1228,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * in from. */ if( sqsh_tok( NULL, &tok, tok_flags ) == False ) { - sqsh_set_error( sqsh_get_error(), "sqsh_tok: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_tok: %s", sqsh_get_errstr() ); return False; } @@ -1259,15 +1242,14 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) } /*-- Now, open the file --*/ - if( (fd = sqsh_open( sqsh_tok_value(tok), O_RDONLY, 0 )) == -1 ) { - sqsh_set_error( sqsh_get_error(), "%s: %s", sqsh_tok_value(tok), - sqsh_get_errstr() ); + cp = sqsh_tok_value(tok); + if( (fd = sqsh_open( cp, O_RDONLY, 0 )) == -1 ) { + sqsh_set_error( sqsh_get_error(), "%s: %s", cp, sqsh_get_errstr() ); return False; } if( (sqsh_dup2( fd, fileno(stdin) )) == -1 ) { - sqsh_set_error( sqsh_get_error(), "%s: %s", sqsh_tok_value(tok), - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "%s: %s", cp, sqsh_get_errstr() ); return False; } sqsh_close( fd ); @@ -1279,8 +1261,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) * dirty work. */ if( sqsh_dup2( tok->tok_fd_right, tok->tok_fd_left ) == -1 ) { - sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "sqsh_dup2: %s", sqsh_get_errstr() ); return False; } @@ -1310,8 +1291,7 @@ static int jobset_parse( js, job, cmd_line, while_buf, tok_flags ) { if (args_add(job->job_args, sqsh_tok_value( tok )) == False) { - sqsh_set_error( sqsh_get_error(), "args_add: %s", - sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "args_add: %s", sqsh_get_errstr() ); return False; } } @@ -1353,13 +1333,13 @@ static job_t* jobset_get( js, job_id ) hval = job_id % js->js_hsize; /*-- Search for the job --*/ - for( j = js->js_jobs[job_id % js->js_hsize]; - j != NULL && j->job_id != job_id; j = j->job_nxt ); + for( j = js->js_jobs[hval]; + j != NULL && j->job_id != job_id; j = j->job_nxt ); /*-- ESTUPID --*/ - if( j == NULL ) { - sqsh_set_error( SQSH_E_EXIST, NULL ); - return NULL; + if( j == NULL ) { + sqsh_set_error( SQSH_E_EXIST, NULL ); + return NULL; } return j; @@ -1460,14 +1440,14 @@ static int jobset_global_init() */ if( sg_cmd_buf == NULL ) { if( (sg_cmd_buf = varbuf_create( 128 )) == NULL ) { - sqsh_set_error( sqsh_get_error(),"varbuf: %s",sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "varbuf: %s", sqsh_get_errstr() ); return False; } } if( sg_alias_buf == NULL ) { if( (sg_alias_buf = varbuf_create( 128 )) == NULL ) { - sqsh_set_error( sqsh_get_error(),"varbuf: %s",sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "varbuf: %s", sqsh_get_errstr() ); return False; } } @@ -1476,7 +1456,7 @@ static int jobset_global_init() { if ((sg_while_buf = varbuf_create( 128 )) == NULL) { - sqsh_set_error( sqsh_get_error(),"varbuf: %s",sqsh_get_errstr() ); + sqsh_set_error( sqsh_get_error(), "varbuf: %s", sqsh_get_errstr() ); return False; } } diff --git a/src/sqsh_main.c b/src/sqsh_main.c index 098dcb1..29601b7 100644 --- a/src/sqsh_main.c +++ b/src/sqsh_main.c @@ -27,9 +27,6 @@ #include <termios.h> #include <pwd.h> #include "sqsh_config.h" -#ifdef HAVE_LOCALE_H -#include <locale.h> -#endif #include "sqsh_job.h" #include "sqsh_error.h" #include "sqsh_global.h" @@ -45,7 +42,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_main.c,v 1.17 2010/02/17 11:35:06 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) */ @@ -148,7 +145,6 @@ main( argc, argv ) char *batch_failcount; char *exit_failcount; char *exit_value; - char *keyword_file; char *term_title; char str[512]; int ch; @@ -166,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. */ @@ -199,15 +204,6 @@ main( argc, argv ) } /* - * Now initialize our system locale, to get a sane default - * character set for the current environment - * This may still be overridden by the -J option - */ -#ifdef HAVE_SETLOCALE - setlocale(LC_ALL, ""); -#endif - - /* * If the first argument on the command line is -r, then we want * to process it before we attempt to read the .sqshrc file (since * -r allows the user to specify another .sqshrc file. @@ -228,6 +224,8 @@ main( argc, argv ) else { rcfile = NULL; + /* sqsh-2.1.9 - Set rcfile environment variable also to NULL */ + env_set( g_env, "rcfile", rcfile ); } } else @@ -279,7 +277,7 @@ main( argc, argv ) if (access( cptr, R_OK ) != -1) { env_set( g_env, "cur_rcfile", cptr ); - if((jobset_run( g_jobset, "\\loop -n $cur_rcfile", &exit_status)) + if((jobset_run( g_jobset, "\\loop -n $cur_rcfile", &exit_status)) == -1 ) { fprintf( stderr, "\\loop: %s\n", sqsh_get_errstr() ); @@ -295,6 +293,8 @@ main( argc, argv ) cptr = strtok( NULL, ":\n\t\r" ); } + /* sqsh-2.1.9 - Remove temporary environment variable cur_rcfile */ + env_remove( g_env, "cur_rcfile", 0); varbuf_destroy(exp_buf); } @@ -309,7 +309,7 @@ main( argc, argv ) "a:A:bBc;C:d:D:eE:f:G:hH:i:I:J:k:K:l:L:m:n:N:o:pP;Q:r;R:s:S:t;T:U:vV;w:Xy:z:Z;\250:" )) != EOF) { ret = 0; - switch (ch) + switch (ch) { case 'a' : ret = env_set( g_env, "thresh_exit", sqsh_optarg ); @@ -377,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 ); @@ -448,19 +447,19 @@ main( argc, argv ) while( *sqsh_optarg != '\0' ) *sqsh_optarg++ = ' '; } - + break; case 'Q' : /* sqsh-2.1.6 */ ret = env_set( g_env, "query_timeout", sqsh_optarg ); break; case 'r' : - /* - * The alternative sqshrc file should already have been - * processed above. Note that the -r option should be the - * first option on the command line, otherwise the option - * is ignored, also the option and the filename should be - * separated by at leat a blank space. - */ + /* + * The alternative sqshrc file should already have been + * processed above. Note that the -r option should be the + * first option on the command line, otherwise the option + * is ignored, also the option and the filename should be + * separated by at leat a blank space. + */ ret = True; break; case 'R' : /* sqsh-2.1.6 */ @@ -520,19 +519,15 @@ main( argc, argv ) case '\250' : #if defined(SQSH_HIDEPWD) { - /* - * sqsh-2.1.7 - Incorporated patch by David Wood - * 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; - + /* + * sqsh-2.1.7 - Incorporated patch by David Wood + * 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. + */ memset(buf, 0, MAXPWD); if (sqsh_optarg != NULL) strcpy (buf, sqsh_optarg); - if (p = strchr(buf, '/')) { + if ((p = strchr(buf, '/')) != NULL) { *p = '\0'; fdin = atoi(buf); fdout = atoi(p+1); @@ -568,7 +563,7 @@ main( argc, argv ) * Check the results from whichever variable we attempted * to set. */ - if (ret == False) + if (ret == False) { fprintf( stderr, "sqsh: -%c: %s\n", ch, sqsh_get_errstr() ); sqsh_exit( 255 ); @@ -594,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]); @@ -622,7 +617,7 @@ main( argc, argv ) sqsh_exit( 255 ); } if (stdin_tty && stdout_tty) - g_interactive = True; + g_interactive = True; #if defined(TIOCGWINSZ) /* @@ -632,24 +627,25 @@ main( argc, argv ) */ if (set_width == False && stdout_tty) { - /* Check to see if the width has been set via the sqshrc file. - To do this we get the current setting - if it is != 80 then - the sqshrc file had a \set width directive, which we don't want - to override here. */ - char *w; - env_get( g_env, "width", &w); - if(!w || atoi(w) == 80) { - if (ioctl(fileno(stdout), TIOCGWINSZ, &ws ) != -1) { - sprintf( str, "%d", ws.ws_col ); - env_set( g_env, "width", str ); - - DBG(sqsh_debug(DEBUG_SCREEN,"sqsh_main: Screen width = %d\n", - ws.ws_col);) - } else { + /* Check to see if the width has been set via the sqshrc file. + * To do this we get the current setting - if it is != 80 then + * the sqshrc file had a \set width directive, which we don't want + * to override here. + */ + char *w; + env_get( g_env, "width", &w); + if(!w || atoi(w) == 80) { + if (ioctl(fileno(stdout), TIOCGWINSZ, &ws ) != -1) { + sprintf( str, "%d", ws.ws_col ); + env_set( g_env, "width", str ); + + DBG(sqsh_debug(DEBUG_SCREEN,"sqsh_main: Screen width = %d\n", + ws.ws_col);) + } else { DBG(sqsh_debug(DEBUG_SCREEN,"sqsh_main: ioctl(%d,TIOCGWINSZ): %s\n", (int)fileno(stdout), strerror(errno));) - } - } + } + } #if defined(SIGWINCH) if (stdout_tty) @@ -703,7 +699,7 @@ main( argc, argv ) * banner. */ env_get( g_env, "banner", &banner ); - if (show_banner && (banner == NULL || *banner == '1') && + if (show_banner && (banner == NULL || *banner == '1') && g_interactive) { printf( "%s ", g_version ); @@ -750,7 +746,7 @@ main( argc, argv ) env_get( g_env, "history", &history ); /* - * If a history file has been defined, then we want to + * If a history file has been defined, then we want to * expand its contents. This will allow folks to have * a different history file for each server. */ @@ -781,31 +777,9 @@ main( argc, argv ) } /* - * If the user has requested some form of keyword completion - * then attempt to read the contents of the keywords file. - * sqsh-2.1.6 feature - Expand keyword_file variable - */ - env_get( g_env, "keyword_file", &keyword_file ); - if ( keyword_file != NULL && *keyword_file != '\0') - { - exp_buf = varbuf_create( 512 ); - if (exp_buf == NULL) - { - fprintf( stderr, "sqsh: %s\n", sqsh_get_errstr() ); - sqsh_exit( 255 ); - } - if (sqsh_expand( keyword_file, exp_buf, 0 ) != False) - sqsh_readline_read( varbuf_getstr( exp_buf) ); - else - fprintf( stderr, "sqsh: Error expanding $keyword_file: %s\n", - sqsh_get_errstr() ); - varbuf_destroy( exp_buf ); - } - - /* * Initialize the readline "sub-system". This basically consists * of installing handlers for readline keyword completion and - * sucking in the readline history file. + * sucking in the completion keyword list and the readline history file. */ sqsh_readline_init(); } @@ -894,6 +868,7 @@ main( argc, argv ) */ sqsh_exit( 0 ); /* NOTREACHED */ + return (0); } #if defined(TIOCGWINSZ) && defined(SIGWINCH) @@ -903,7 +878,7 @@ main( argc, argv ) * * This function is called whenever a SIGWINCH (window size change) * signal is recieved during the life of sqsh. Unfortunately, this - * function calls quite a few functions that are known not to be + * function calls quite a few functions that are known not to be * signal safe, but I am willing to accept the risk. Thanks * to David Whitemarsh <djw@accessio.demon.co.uk> for supplying * this code. @@ -926,7 +901,7 @@ static void sigwinch_handler( sig, user_data ) if (isatty( fileno(stdout) )) ctty_fd = fileno(stdout); else { - + /* * Attempt to grab the path to our controlling tty. If we can't * find it, then we have to give up. @@ -999,7 +974,7 @@ static void print_usage() sprintf( str, " [%s]", sg_flags[i].flag ); else sprintf( str, " [%s %s]", sg_flags[i].flag, sg_flags[i].arg ); - + len = strlen( str ); if( (line_len + len) > 68 ) { @@ -1037,60 +1012,117 @@ static void print_usage() * sqsh-2.1.7 - Incorporated patch by David Wood * 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. + * sqsh-2.2.0 - Function reworked. */ static void hide_password (argc, argv) int argc; char *argv[]; { - int i, j; - int filedes[2]; - char buf[32]; - char nullpwd[2]; - char *pwd = NULL; - - for (i = 1; i < argc; ++i) { - if (*(argv[i]) == '-' && *(argv[i] + 1) == 'P') { - if (*(argv[i]+2)) { - pwd = (argv[i]+2); /* Password passed on as: "sqsh -SSYBASE -Usa -Pxxxxxx" */ - } else if (i + 1 < argc && *(argv[i + 1]) != '-') { - pwd = argv[i + 1]; /* Password passed on as: "sqsh -SSYBASE -Usa -P xxxxxx" */ - /* Reshuffle the argv list to remove the password string */ - for (j = i + 1; j < argc - 1; j++) - argv[j] = argv[j + 1]; - argv[j] = NULL; - argc--; + int i, j; + char buf[32]; + int filedes[2]; + char nullpwd[2]; + pid_t pid; + char *pwd = NULL; + int status; + + + nullpwd[0] = '\n'; + nullpwd[1] = '\0'; + + /* + * Loop through the list of arguments only once and skip all intermediate -P + * entries, but remember the last password specified. + */ + for (i = 0, j = 0; argv[i] != NULL; ++i) + { + if (*(argv[i]) == '-' && *(argv[i]+1) == 'P') + { + /* + * New password parameter encounterd. + */ + pwd = NULL; + if (*(argv[i]+2) != '\0') + { + /* + * Password passed on as: "sqsh -SSYBASE -Usa -Pxxxxxx" , or as -P- + */ + pwd = (argv[i]+2); + } + else if ((i+1 < argc) && (*(argv[i+1]) != '-' || (*(argv[i+1]) == '-' && *(argv[i+1]+1) == '\0'))) + { + /* + * Password passed on as: "sqsh -SSYBASE -Usa -P xxxxxx" , or as -P - + */ + pwd = argv[++i]; } if (pwd == NULL || (pwd != NULL && strlen(pwd) == 0)) { - nullpwd[0] = '\n'; - nullpwd[1] = '\0'; - pwd = nullpwd; /* Empty (NULL) password passed on as: - * "sqsh -SSYBASE -Usa -P " or "sqsh -SSYBASE -Usa -P '' " */ + /* + * Empty (NULL) password passed on as: + * "sqsh -SSYBASE -Usa -P " or "sqsh -SSYBASE -Usa -P '' " + */ + pwd = nullpwd; } + } + else + argv[j++] = argv[i]; + } - /* Create the pipe... */ - if (pipe(filedes) == -1) { - perror("sqsh: Error: Can't pipe()"); - return; - } - sprintf(buf, "-%c%d/%d", '\250', filedes[0], filedes[1]); - argv[i] = buf; - - if (fork()) { - /* Re-execute ourselves, with the modified argv[] */ - execvp(argv[0], argv); - /* Not reached */ - } else { - /* ... and write the password to the pipe */ - if (write(filedes[1], pwd, strlen(pwd)) != 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]); - sqsh_exit(0); - } + /* + * If pwd == NULL then no -P was specified as argument and we do not + * have to hide anything from the argument list. + */ + if (pwd == NULL) + { + return; + } + + /* + * Create the pipe. + */ + if (pipe (filedes) == -1) + { + perror ("sqsh: Error: Can't pipe()"); + return; + } + sprintf (buf, "-%c%d/%d", '\250', filedes[0], filedes[1]); + argv[j++] = buf; + argv[j] = NULL; + + 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. + */ + (void) waitpid (pid, &status, 0); + /* + * Re-execute ourselves in the parent process, with the modified argv[] list. + */ + if (WIFEXITED(status) != 0 && WEXITSTATUS(status) == 0) + (void) execvp (argv[0], argv); + /* Not reached */ + else + { + fprintf (stderr, "sqsh: Error: Processing of function hide_password failed unexpectedly\n"); + sqsh_exit (255); + } + } + else + { + /* + * The child process writes the password to the pipe, closes the pipe + * and exits. + */ + 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); } + (void) close (filedes[0]); + (void) close (filedes[1]); + sqsh_exit (0); } } diff --git a/src/sqsh_parser/Makefile.in b/src/sqsh_parser/Makefile.in new file mode 100644 index 0000000..ef22495 --- /dev/null +++ b/src/sqsh_parser/Makefile.in @@ -0,0 +1,31 @@ +CC = @CC@ +CFLAGS = -c @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +OBJMODE = @OBJMODE@ +LEX = flex -Cm +LEMON = lemon -q + +libsqsh: sqsh_parser.o tsql.o tsql.yy.o + ar -rcsv ${OBJMODE} sqsh_parser.a sqsh_parser.o tsql.o tsql.yy.o + +sqsh_parser.o: sqsh_parser.c sqsh_parser.h + ${CC} $(CFLAGS) -o $@ sqsh_parser.c + +tsql.o: tsql.c sqsh_parser.h + ${CC} $(CFLAGS) -o $@ tsql.c + +tsql.yy.o: tsql.yy.c tsql.h + ${CC} $(CFLAGS) -o $@ tsql.yy.c + +tsql.c: tsql.y + ${LEMON} -s -q tsql.y + +tsql.yy.c: tsql.l + ${LEX} -o tsql.yy.c tsql.l + +clean: + rm -f sqsh_parser.o tsql.o tsql.yy.o sqsh_parser.a + +distclean: + rm -f Makefile sqsh_parser.o tsql.o tsql.yy.o sqsh_parser.a +# rm -f Makefile sqsh_parser.o tsql.o tsql.yy.o tsql.c tsql.yy.c tsql.h sqsh_parser.a diff --git a/src/sqsh_parser/sqsh_parser.c b/src/sqsh_parser/sqsh_parser.c new file mode 100644 index 0000000..c3014df --- /dev/null +++ b/src/sqsh_parser/sqsh_parser.c @@ -0,0 +1,129 @@ +/* + * File: main.c + * Author: K.-M. Hansche + * + * Created on 19. Juli 2013, 07:41 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <search.h> +#include <string.h> +#include <ctype.h> + +#include "sqsh_parser.h" + +void* def_root = NULL; +aliascallback callback = NULL; +long callbacklparam = 0; + +static void* xmalloc(size_t size) { + void* m = malloc(size); + if (m == NULL) { + exit(0); + } + memset(m, 0, size); + return m; +} + +static void free_node(void *nodep) { + t_tdef* datap; + datap = (t_tdef*) nodep; + + free(datap->alias); + free(datap->table); + free(datap); + +} + +static int def_compare(const void *pa, const void *pb) { + return strcmp(((t_tdef*) pa)->alias, ((t_tdef*) pb)->alias); +} + +void* addTableDefNode(char* table, char* alias) { + if (table == NULL) return NULL; + if (alias == NULL || strcmp(alias, "") == 0) alias = table; + + t_tdef* tdef = (t_tdef*) xmalloc(sizeof (t_tdef)); + tdef->table = (char(*)) xmalloc((strlen(table) + 1) * sizeof (char)); + tdef->alias = (char(*)) xmalloc((strlen(alias) + 1) * sizeof (char)); + + strcpy(tdef->table, table); + strcpy(tdef->alias, alias); + + void* p = tsearch(tdef, &def_root, def_compare); + if (tdef != *(t_tdef **) p) { + free_node(tdef); + } + + return p; +} + +static void callback_walker(const void *nodep, const VISIT which, const int depth) { + t_tdef* datap; + + datap = *(t_tdef**) nodep; + + switch (which) { + case preorder: + case endorder: + break; + case postorder: + case leaf: + callback(datap->table, datap->alias, callbacklparam); + break; + } +} + +static void print_walker(const void *nodep, const VISIT which, const int depth) { + t_tdef* datap; + + datap = *(t_tdef**) nodep; + + switch (which) { + case preorder: + break; + case postorder: + printf("Table: %s\t alias: %s\t depth: %i\n", datap->table, datap->alias, depth); + break; + case endorder: + break; + case leaf: + printf("Table: %s\t alias: %s\t depth: %i\tLeaf\n", datap->table, datap->alias, depth); + break; + } +} + +void delTableDefs(void) { +#if !defined(_GNU_SOURCE) + t_tdef* datap; + + while (def_root != NULL) { + datap = *(t_tdef**)def_root; + tdelete((void *)datap, &def_root, def_compare); + free_node(datap); + } +#else + tdestroy(def_root, free_node); + def_root = NULL; +#endif +} + +char* getTableForAlias(char* alias) { + t_tdef tdef; + t_tdef** res; + + if (alias == NULL) return NULL; + + tdef.alias = alias; + res = tfind(&tdef, &def_root, def_compare); + + return res != NULL ? (*res)->table : NULL; +} + +void getTablesAndAliases(aliascallback cb, long lparam){ + callback=cb; + callbacklparam=lparam; + twalk(def_root, callback_walker); +} + diff --git a/src/sqsh_parser/sqsh_parser.h b/src/sqsh_parser/sqsh_parser.h new file mode 100644 index 0000000..b8659bf --- /dev/null +++ b/src/sqsh_parser/sqsh_parser.h @@ -0,0 +1,65 @@ +/* + * File: sqsh_parser.h + * Author: K.-M. Hansche + * + * Created on 22. Juli 2013, 17:37 + */ + +#ifndef SQSH_PARSER_H +#define SQSH_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + + typedef void (* aliascallback)(char* table, char* alias, long lparam); + + /** + * Extract table/alias combos from an arbitrary sql-statement. + * Please call delTabledefs after you are done. + * + * @param sql A complete or incomplete sql-statement. + */ + extern void parseSql(char* sql); + + /** + * + * @param alias The alias (or tablename, for simplicity) you want to get the + * tablename for. + * @return The tablename or NULL. The string will be freed on delTableDefs. + */ + extern char* getTableForAlias(char* alias); + + /** + * Free all resources, including strings from getTableForAlias. + */ + extern void delTableDefs(void); + + /** + * Insert a tabledefinition into the global tree. + * The strings are duplicated internally and freed on delTabledefs. + * + * @param table A tablename + * @param alias The used alias for that name. May be NULL. + * @return + */ + extern void* addTableDefNode(char* table, char* alias); + + /** + * Iterate over all data. Calls cb for every table/alias-pair. + * @param cb A callback defined as typedef void (* aliascallback)(char* table, char* alias, long lparam); + * @param lparam The user-defined lparam for cb; + */ + extern void getTablesAndAliases(aliascallback cb, long lparam); + + typedef struct { + char* table; + char* alias; + } t_tdef; + +#ifdef __cplusplus +} +#endif + +#endif /* SQSH_PARSER_H */ + diff --git a/src/sqsh_parser/tsql.c b/src/sqsh_parser/tsql.c new file mode 100644 index 0000000..dc19062 --- /dev/null +++ b/src/sqsh_parser/tsql.c @@ -0,0 +1,970 @@ +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. +*/ +/* First off, code is included that follows the "include" declaration +** in the input grammar file. */ +#include <stdio.h> +#line 1 "tsql.y" + + #include <string.h> + #include <assert.h> + #include <stdlib.h> + + #include "sqsh_parser.h" +#line 15 "tsql.c" +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control +** various aspects of the generated parser. +** YYCODETYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 terminals +** and nonterminals. "int" is used otherwise. +** YYNOCODE is a number of type YYCODETYPE which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. +** YYFALLBACK If defined, this indicates that one or more tokens +** have fall-back values which should be used if the +** original value of the token will not parse. +** YYACTIONTYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 rules and +** states combined. "int" is used otherwise. +** ParseTOKENTYPE is the data type used for minor tokens given +** directly to the parser from the tokenizer. +** YYMINORTYPE is the data type used for all minor tokens. +** This is typically a union of many types, one of +** which is ParseTOKENTYPE. The entry in the union +** for base tokens is called "yy0". +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() +** ParseARG_SDECL A static variable declaration for the %extra_argument +** ParseARG_PDECL A parameter declaration for the %extra_argument +** ParseARG_STORE Code to store %extra_argument into yypParser +** ParseARG_FETCH Code to extract %extra_argument from yypParser +** YYNSTATE the combined number of states. +** YYNRULE the number of rules in the grammar +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +*/ +#define YYCODETYPE unsigned char +#define YYNOCODE 13 +#define YYACTIONTYPE unsigned char +#define ParseTOKENTYPE char* +typedef union { + int yyinit; + ParseTOKENTYPE yy0; +} YYMINORTYPE; +#ifndef YYSTACKDEPTH +#define YYSTACKDEPTH 100 +#endif +#define ParseARG_SDECL +#define ParseARG_PDECL +#define ParseARG_FETCH +#define ParseARG_STORE +#define YYNSTATE 15 +#define YYNRULE 10 +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) + +/* The yyzerominor constant is used to initialize instances of +** YYMINORTYPE objects to zero. */ +static const YYMINORTYPE yyzerominor = { 0 }; + +/* Define the yytestcase() macro to be a no-op if is not already defined +** otherwise. +** +** Applications can choose to define yytestcase() in the %include section +** to a macro that can assist in verifying code coverage. For production +** code the yytestcase() macro should be turned off. But it is useful +** for testing. +*/ +#ifndef yytestcase +# define yytestcase(X) +#endif + + +/* Next are the tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead +** token onto the stack and goto state N. +** +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. +** +** N == YYNSTATE+YYNRULE A syntax error has occurred. +** +** N == YYNSTATE+YYNRULE+1 The parser accepts its input. +** +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as +** +** yy_action[ yy_shift_ofst[S] + X ] +** +** If the index value yy_shift_ofst[S]+X is out of range or if the value +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table +** and that yy_default[S] should be used instead. +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** yy_action[] A single table containing all actions. +** yy_lookahead[] A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** yy_shift_ofst[] For each state, the offset into yy_action for +** shifting terminals. +** yy_reduce_ofst[] For each state, the offset into yy_action for +** shifting non-terminals after a reduce. +** yy_default[] Default action for each state. +*/ +#define YY_ACTTAB_COUNT (18) +static const YYACTIONTYPE yy_action[] = { + /* 0 */ 15, 7, 12, 1, 26, 2, 8, 4, 3, 5, + /* 10 */ 9, 7, 10, 1, 13, 11, 6, 14, +}; +static const YYCODETYPE yy_lookahead[] = { + /* 0 */ 0, 1, 11, 3, 7, 8, 9, 4, 5, 10, + /* 10 */ 11, 1, 11, 3, 2, 2, 2, 9, +}; +#define YY_SHIFT_USE_DFLT (-1) +#define YY_SHIFT_COUNT (7) +#define YY_SHIFT_MIN (0) +#define YY_SHIFT_MAX (14) +static const signed char yy_shift_ofst[] = { + /* 0 */ 10, 14, 0, 14, 14, 3, 13, 12, +}; +#define YY_REDUCE_USE_DFLT (-10) +#define YY_REDUCE_COUNT (4) +#define YY_REDUCE_MIN (-9) +#define YY_REDUCE_MAX (8) +static const signed char yy_reduce_ofst[] = { + /* 0 */ -3, -1, 8, 1, -9, +}; +static const YYACTIONTYPE yy_default[] = { + /* 0 */ 25, 25, 25, 25, 25, 19, 23, 25, 17, 20, + /* 10 */ 22, 24, 21, 18, 16, +}; + +/* The next table maps tokens into fallback tokens. If a construct +** like the following: +** +** %fallback ID X Y Z. +** +** appears in the grammar, then ID becomes a fallback token for X, Y, +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +*/ +#ifdef YYFALLBACK +static const YYCODETYPE yyFallback[] = { +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack. Information stored includes: +** +** + The state number for the parser at this level of the stack. +** +** + The value of the token stored at this level of the stack. +** (In other words, the "major" token.) +** +** + The semantic value stored at this level of the stack. This is +** the information used by the action routines in the grammar. +** It is sometimes called the "minor" token. +*/ +struct yyStackEntry { + YYACTIONTYPE stateno; /* The state-number */ + YYCODETYPE major; /* The major token value. This is the code + ** number for the token at this stack level */ + YYMINORTYPE minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; +typedef struct yyStackEntry yyStackEntry; + +/* The state of the parser is completely contained in an instance of +** the following structure */ +struct yyParser { + int yyidx; /* Index of top element in stack */ +#ifdef YYTRACKMAXSTACKDEPTH + int yyidxMax; /* Maximum value of yyidx */ +#endif + int yyerrcnt; /* Shifts left before out of the error */ + ParseARG_SDECL /* A place to hold %extra_argument */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +#else + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ +#endif +}; +typedef struct yyParser yyParser; + +#ifndef NDEBUG +#include <stdio.h> +static FILE *yyTraceFILE = 0; +static char *yyTracePrompt = 0; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message. Tracing is turned off +** by making either argument NULL +** +** Inputs: +** <ul> +** <li> A FILE* to which trace output should be written. +** If NULL, then tracing is turned off. +** <li> A prefix string written at the beginning of every +** line of trace output. If NULL, then tracing is +** turned off. +** </ul> +** +** Outputs: +** None. +*/ +void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ + yyTraceFILE = TraceFILE; + yyTracePrompt = zTracePrompt; + if( yyTraceFILE==0 ) yyTracePrompt = 0; + else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required. The following table supplies these names */ +static const char *const yyTokenName[] = { + "$", "INSUP", "TOKEN", "FROM", + "COMMA", "JOIN", "error", "prog", + "statements", "statement", "tabledefs", "tabledef", +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +static const char *const yyRuleName[] = { + /* 0 */ "prog ::= statements", + /* 1 */ "statements ::= statements statement", + /* 2 */ "statements ::= statement", + /* 3 */ "statement ::= INSUP TOKEN", + /* 4 */ "statement ::= FROM tabledefs", + /* 5 */ "tabledefs ::= tabledef", + /* 6 */ "tabledefs ::= tabledefs COMMA tabledef", + /* 7 */ "tabledefs ::= tabledefs JOIN tabledef", + /* 8 */ "tabledef ::= TOKEN", + /* 9 */ "tabledef ::= TOKEN TOKEN", +}; +#endif /* NDEBUG */ + + +#if YYSTACKDEPTH<=0 +/* +** Try to increase the size of the parser stack. +*/ +static void yyGrowStack(yyParser *p){ + int newSize; + yyStackEntry *pNew; + + newSize = p->yystksz*2 + 100; + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + if( pNew ){ + p->yystack = pNew; + p->yystksz = newSize; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", + yyTracePrompt, p->yystksz); + } +#endif + } +} +#endif + +/* +** This function allocates a new parser. +** The only argument is a pointer to a function which works like +** malloc. +** +** Inputs: +** A pointer to the function used to allocate memory. +** +** Outputs: +** A pointer to a parser. This pointer is used in subsequent calls +** to Parse and ParseFree. +*/ +void *ParseAlloc(void *(*mallocProc)(size_t)){ + yyParser *pParser; + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); + if( pParser ){ + pParser->yyidx = -1; +#ifdef YYTRACKMAXSTACKDEPTH + pParser->yyidxMax = 0; +#endif +#if YYSTACKDEPTH<=0 + pParser->yystack = NULL; + pParser->yystksz = 0; + yyGrowStack(pParser); +#endif + } + return pParser; +} + +/* The following function deletes the value associated with a +** symbol. The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. +*/ +static void yy_destructor( + yyParser *yypParser, /* The parser */ + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ +){ + ParseARG_FETCH; + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are not used + ** inside the C code. + */ + /* TERMINAL Destructor */ + case 1: /* INSUP */ + case 2: /* TOKEN */ + case 3: /* FROM */ + case 4: /* COMMA */ + case 5: /* JOIN */ +{ +#line 14 "tsql.y" +free((yypminor->yy0)); +#line 375 "tsql.c" +} + break; + default: break; /* If no destructor action specified: do nothing */ + } +} + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. +*/ +static int yy_pop_parser_stack(yyParser *pParser){ + YYCODETYPE yymajor; + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + + if( pParser->yyidx<0 ) return 0; +#ifndef NDEBUG + if( yyTraceFILE && pParser->yyidx>=0 ){ + fprintf(yyTraceFILE,"%sPopping %s\n", + yyTracePrompt, + yyTokenName[yytos->major]); + } +#endif + yymajor = yytos->major; + yy_destructor(pParser, yymajor, &yytos->minor); + pParser->yyidx--; + return yymajor; +} + +/* +** Deallocate and destroy a parser. Destructors are all called for +** all stack elements before shutting the parser down. +** +** Inputs: +** <ul> +** <li> A pointer to the parser. This should be a pointer +** obtained from ParseAlloc. +** <li> A pointer to a function used to reclaim memory obtained +** from malloc. +** </ul> +*/ +void ParseFree( + void *p, /* The parser to be deleted */ + void (*freeProc)(void*) /* Function used to reclaim memory */ +){ + yyParser *pParser = (yyParser*)p; + if( pParser==0 ) return; + while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + free(pParser->yystack); +#endif + (*freeProc)((void*)pParser); +} + +/* +** Return the peak depth of the stack for a parser. +*/ +#ifdef YYTRACKMAXSTACKDEPTH +int ParseStackPeak(void *p){ + yyParser *pParser = (yyParser*)p; + return pParser->yyidxMax; +} +#endif + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_shift_action( + yyParser *pParser, /* The parser */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; + int stateno = pParser->yystack[pParser->yyidx].stateno; + + if( stateno>YY_SHIFT_COUNT + || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ + return yy_default[stateno]; + } + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ +#ifdef YYFALLBACK + YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) + && (iFallback = yyFallback[iLookAhead])!=0 ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + return yy_find_shift_action(pParser, iFallback); + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j<YY_ACTTAB_COUNT && +#endif + yy_lookahead[j]==YYWILDCARD + ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; + } + } +#endif /* YYWILDCARD */ + } + return yy_default[stateno]; + }else{ + return yy_action[i]; + } +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_reduce_action( + int stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; +#ifdef YYERRORSYMBOL + if( stateno>YY_REDUCE_COUNT ){ + return yy_default[stateno]; + } +#else + assert( stateno<=YY_REDUCE_COUNT ); +#endif + i = yy_reduce_ofst[stateno]; + assert( i!=YY_REDUCE_USE_DFLT ); + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; +#ifdef YYERRORSYMBOL + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + } +#else + assert( i>=0 && i<YY_ACTTAB_COUNT ); + assert( yy_lookahead[i]==iLookAhead ); +#endif + return yy_action[i]; +} + +/* +** The following routine is called if the stack overflows. +*/ +static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ + ParseARG_FETCH; + yypParser->yyidx--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ + ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ +} + +/* +** Perform a shift action. +*/ +static void yy_shift( + yyParser *yypParser, /* The parser to be shifted */ + int yyNewState, /* The new state to shift in */ + int yyMajor, /* The major token to shift in */ + YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ +){ + yyStackEntry *yytos; + yypParser->yyidx++; +#ifdef YYTRACKMAXSTACKDEPTH + if( yypParser->yyidx>yypParser->yyidxMax ){ + yypParser->yyidxMax = yypParser->yyidx; + } +#endif +#if YYSTACKDEPTH>0 + if( yypParser->yyidx>=YYSTACKDEPTH ){ + yyStackOverflow(yypParser, yypMinor); + return; + } +#else + if( yypParser->yyidx>=yypParser->yystksz ){ + yyGrowStack(yypParser); + if( yypParser->yyidx>=yypParser->yystksz ){ + yyStackOverflow(yypParser, yypMinor); + return; + } + } +#endif + yytos = &yypParser->yystack[yypParser->yyidx]; + yytos->stateno = (YYACTIONTYPE)yyNewState; + yytos->major = (YYCODETYPE)yyMajor; + yytos->minor = *yypMinor; +#ifndef NDEBUG + if( yyTraceFILE && yypParser->yyidx>0 ){ + int i; + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); + for(i=1; i<=yypParser->yyidx; i++) + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); + fprintf(yyTraceFILE,"\n"); + } +#endif +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + unsigned char nrhs; /* Number of right-hand side symbols in the rule */ +} yyRuleInfo[] = { + { 7, 1 }, + { 8, 2 }, + { 8, 1 }, + { 9, 2 }, + { 9, 2 }, + { 10, 1 }, + { 10, 3 }, + { 10, 3 }, + { 11, 1 }, + { 11, 2 }, +}; + +static void yy_accept(yyParser*); /* Forward Declaration */ + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +static void yy_reduce( + yyParser *yypParser, /* The parser */ + int yyruleno /* Number of the rule by which to reduce */ +){ + int yygoto; /* The next state */ + int yyact; /* The next action */ + YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ + ParseARG_FETCH; + yymsp = &yypParser->yystack[yypParser->yyidx]; +#ifndef NDEBUG + if( yyTraceFILE && yyruleno>=0 + && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, + yyRuleName[yyruleno]); + } +#endif /* NDEBUG */ + + /* Silence complaints from purify about yygotominor being uninitialized + ** in some cases when it is copied into the stack after the following + ** switch. yygotominor is uninitialized when a rule reduces that does + ** not set the value of its left-hand side nonterminal. Leaving the + ** value of the nonterminal uninitialized is utterly harmless as long + ** as the value is never used. So really the only thing this code + ** accomplishes is to quieten purify. + ** + ** 2007-01-16: The wireshark project (www.wireshark.org) reports that + ** without this code, their parser segfaults. I'm not sure what there + ** parser is doing to make this happen. This is the second bug report + ** from wireshark this week. Clearly they are stressing Lemon in ways + ** that it has not been previously stressed... (SQLite ticket #2172) + */ + /*memset(&yygotominor, 0, sizeof(yygotominor));*/ + yygotominor = yyzerominor; + + + switch( yyruleno ){ + /* Beginning here are the reduction cases. A typical example + ** follows: + ** case 0: + ** #line <lineno> <grammarfile> + ** { ... } // User supplied code + ** #line <lineno> <thisfile> + ** break; + */ + case 3: /* statement ::= INSUP TOKEN */ +#line 19 "tsql.y" +{addTableDefNode(yymsp[0].minor.yy0, yymsp[0].minor.yy0);free(yymsp[0].minor.yy0); yy_destructor(yypParser,1,&yymsp[-1].minor); +} +#line 681 "tsql.c" + break; + case 4: /* statement ::= FROM tabledefs */ +#line 20 "tsql.y" +{ + yy_destructor(yypParser,3,&yymsp[-1].minor); +} +#line 688 "tsql.c" + break; + case 6: /* tabledefs ::= tabledefs COMMA tabledef */ +#line 22 "tsql.y" +{ + yy_destructor(yypParser,4,&yymsp[-1].minor); +} +#line 695 "tsql.c" + break; + case 7: /* tabledefs ::= tabledefs JOIN tabledef */ +#line 23 "tsql.y" +{ + yy_destructor(yypParser,5,&yymsp[-1].minor); +} +#line 702 "tsql.c" + break; + case 8: /* tabledef ::= TOKEN */ +#line 24 "tsql.y" +{addTableDefNode(yymsp[0].minor.yy0, yymsp[0].minor.yy0); free(yymsp[0].minor.yy0);} +#line 707 "tsql.c" + break; + case 9: /* tabledef ::= TOKEN TOKEN */ +#line 25 "tsql.y" +{addTableDefNode(yymsp[-1].minor.yy0, yymsp[0].minor.yy0); free(yymsp[-1].minor.yy0); free(yymsp[0].minor.yy0);} +#line 712 "tsql.c" + break; + default: + /* (0) prog ::= statements */ yytestcase(yyruleno==0); + /* (1) statements ::= statements statement */ yytestcase(yyruleno==1); + /* (2) statements ::= statement */ yytestcase(yyruleno==2); + /* (5) tabledefs ::= tabledef */ yytestcase(yyruleno==5); + break; + }; + yygoto = yyRuleInfo[yyruleno].lhs; + yysize = yyRuleInfo[yyruleno].nrhs; + yypParser->yyidx -= yysize; + yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); + if( yyact < YYNSTATE ){ +#ifdef NDEBUG + /* If we are not debugging and the reduce action popped at least + ** one element off the stack, then we can push the new element back + ** onto the stack here, and skip the stack overflow test in yy_shift(). + ** That gives a significant speed improvement. */ + if( yysize ){ + yypParser->yyidx++; + yymsp -= yysize-1; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yymsp->minor = yygotominor; + }else +#endif + { + yy_shift(yypParser,yyact,yygoto,&yygotominor); + } + }else{ + assert( yyact == YYNSTATE + YYNRULE + 1 ); + yy_accept(yypParser); + } +} + +/* +** The following code executes when the parse fails +*/ +#ifndef YYNOERRORRECOVERY +static void yy_parse_failed( + yyParser *yypParser /* The parser */ +){ + ParseARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser fails */ +#line 9 "tsql.y" + + //Actually we don't expect everything to parse. +#line 767 "tsql.c" + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} +#endif /* YYNOERRORRECOVERY */ + +/* +** The following code executes when a syntax error first occurs. +*/ +static void yy_syntax_error( + yyParser *yypParser, /* The parser */ + int yymajor, /* The major type of the error token */ + YYMINORTYPE yyminor /* The minor type of the error token */ +){ + ParseARG_FETCH; +#define TOKEN (yyminor.yy0) + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following is executed when the parser accepts +*/ +static void yy_accept( + yyParser *yypParser /* The parser */ +){ + ParseARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser accepts */ + ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "ParseAlloc" which describes the current state of the parser. +** The second argument is the major token number. The third is +** the minor token. The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +** <ul> +** <li> A pointer to the parser (an opaque structure.) +** <li> The major token number. +** <li> The minor token number. +** <li> An option argument of a grammar-specified type. +** </ul> +** +** Outputs: +** None. +*/ +void Parse( + void *yyp, /* The parser */ + int yymajor, /* The major token code number */ + ParseTOKENTYPE yyminor /* The value for the token */ + ParseARG_PDECL /* Optional %extra_argument parameter */ +){ + YYMINORTYPE yyminorunion; + int yyact; /* The parser action. */ + int yyendofinput; /* True if we are at the end of input */ +#ifdef YYERRORSYMBOL + int yyerrorhit = 0; /* True if yymajor has invoked an error */ +#endif + yyParser *yypParser; /* The parser */ + + /* (re)initialize the parser, if necessary */ + yypParser = (yyParser*)yyp; + if( yypParser->yyidx<0 ){ +#if YYSTACKDEPTH<=0 + if( yypParser->yystksz <=0 ){ + /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ + yyminorunion = yyzerominor; + yyStackOverflow(yypParser, &yyminorunion); + return; + } +#endif + yypParser->yyidx = 0; + yypParser->yyerrcnt = -1; + yypParser->yystack[0].stateno = 0; + yypParser->yystack[0].major = 0; + } + yyminorunion.yy0 = yyminor; + yyendofinput = (yymajor==0); + ParseARG_STORE; + +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); + } +#endif + + do{ + yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); + if( yyact<YYNSTATE ){ + assert( !yyendofinput ); /* Impossible to shift the $ token */ + yy_shift(yypParser,yyact,yymajor,&yyminorunion); + yypParser->yyerrcnt--; + yymajor = YYNOCODE; + }else if( yyact < YYNSTATE + YYNRULE ){ + yy_reduce(yypParser,yyact-YYNSTATE); + }else{ + assert( yyact == YY_ERROR_ACTION ); +#ifdef YYERRORSYMBOL + int yymx; +#endif +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); + } +#endif +#ifdef YYERRORSYMBOL + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if( yypParser->yyerrcnt<0 ){ + yy_syntax_error(yypParser,yymajor,yyminorunion); + } + yymx = yypParser->yystack[yypParser->yyidx].major; + if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sDiscard input token %s\n", + yyTracePrompt,yyTokenName[yymajor]); + } +#endif + yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion); + yymajor = YYNOCODE; + }else{ + while( + yypParser->yyidx >= 0 && + yymx != YYERRORSYMBOL && + (yyact = yy_find_reduce_action( + yypParser->yystack[yypParser->yyidx].stateno, + YYERRORSYMBOL)) >= YYNSTATE + ){ + yy_pop_parser_stack(yypParser); + } + if( yypParser->yyidx < 0 || yymajor==0 ){ + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + yy_parse_failed(yypParser); + yymajor = YYNOCODE; + }else if( yymx!=YYERRORSYMBOL ){ + YYMINORTYPE u2; + u2.YYERRSYMDT = 0; + yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); + } + } + yypParser->yyerrcnt = 3; + yyerrorhit = 1; +#elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax + ** error routine and continue going as if nothing had happened. + ** + ** Applications can set this macro (for example inside %include) if + ** they intend to abandon the parse upon the first syntax error seen. + */ + yy_syntax_error(yypParser,yymajor,yyminorunion); + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + yymajor = YYNOCODE; + +#else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if( yypParser->yyerrcnt<=0 ){ + yy_syntax_error(yypParser,yymajor,yyminorunion); + } + yypParser->yyerrcnt = 3; + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + if( yyendofinput ){ + yy_parse_failed(yypParser); + } + yymajor = YYNOCODE; +#endif + } + }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); + return; +} diff --git a/src/sqsh_parser/tsql.h b/src/sqsh_parser/tsql.h new file mode 100644 index 0000000..690892d --- /dev/null +++ b/src/sqsh_parser/tsql.h @@ -0,0 +1,5 @@ +#define INSUP 1 +#define TOKEN 2 +#define FROM 3 +#define COMMA 4 +#define JOIN 5 diff --git a/src/sqsh_parser/tsql.l b/src/sqsh_parser/tsql.l new file mode 100644 index 0000000..911a3e7 --- /dev/null +++ b/src/sqsh_parser/tsql.l @@ -0,0 +1,69 @@ +%{ +#include "tsql.h" + +#define KW(w) {return w;} + +%} + +%option noyywrap +%option warn +%option 8bit +%s INFROM +%s INDML + + +alpha [A-Za-zäöüß_] +anum [A-Za-z0-9_äöüß_\.\-] +anumsp [A-Za-z0-9_äöüß_ \.\-] +ws [ \t\r\n] + +%% + +<INITIAL>from/{ws}+ {BEGIN INFROM; KW(FROM);} +<INITIAL>(?i:insert|update|delete)/{ws}+ {BEGIN INDML; KW(INSUP);} +<INITIAL>(?i:insert{ws}+into)/{ws}+ {BEGIN INDML; KW(INSUP);} +<INITIAL,INFROM>(?i:join)/{ws}+ {BEGIN INFROM; KW(JOIN);} +<INFROM>(?i:inner|left|right|outer)/{ws}+ {BEGIN INITIAL;} +<INFROM>(?i:where|on)/{ws}+ {BEGIN INITIAL;} +<INFROM>{alpha}{anum}* {KW(TOKEN);} +<INFROM>\"{alpha}{anumsp}*\" {KW(TOKEN);} +<INFROM>\[{alpha}{anumsp}*\] {KW(TOKEN);} +<INDML>{alpha}{anum}* {BEGIN INITIAL; KW(TOKEN);} +<INDML>\"{alpha}{anumsp}*\" {BEGIN INITIAL; KW(TOKEN);} +<INDML>\[{alpha}{anumsp}*\] {BEGIN INITIAL; KW(TOKEN);} +<INFROM>, {KW(COMMA);} +<INFROM>"(" {BEGIN INITIAL;} +. ; +[\n] ; + + +%% + +int testlex(char *buffer) +{ + yy_scan_string(buffer); + int rl; + + while ((rl=yylex())!=0){ + printf("Token: %i yytext: %s\n", rl, yytext); + } + yylex_destroy(); + return 0; +} + +extern void *ParseAlloc(void *(*mallocProc)(size_t)); +extern void ParseFree(void *p, void (*freeProc)(void*)); +extern void Parse(void *yyp, int yymajor, void* yyminor); +void parseSql(char* sql) { + int lr; + void* pParser = ParseAlloc(malloc); + + yy_scan_string(sql); + + while ((lr=yylex())!=0){ + Parse(pParser, lr, strdup(yytext)); + } + Parse(pParser, 0, NULL); + ParseFree(pParser, free); + yylex_destroy(); +} diff --git a/src/sqsh_parser/tsql.y b/src/sqsh_parser/tsql.y new file mode 100644 index 0000000..55e345b --- /dev/null +++ b/src/sqsh_parser/tsql.y @@ -0,0 +1,25 @@ +%include { + #include <string.h> + #include <assert.h> + #include <stdlib.h> + + #include "sqsh_parser.h" +} + +%parse_failure { + //Actually we don't expect everything to parse. +} + +%token_type {char*} +%token_destructor {free($$);} + +prog ::= statements. +statements ::= statements statement. +statements ::= statement. +statement ::= INSUP TOKEN(B). {addTableDefNode(B, B);free(B);} +statement ::= FROM tabledefs. +tabledefs ::= tabledef. +tabledefs ::= tabledefs COMMA tabledef. +tabledefs ::= tabledefs JOIN tabledef. // Right, "on"-clauses are filtered by the lexer. +tabledef ::= TOKEN(B). {addTableDefNode(B, B); free(B);} +tabledef ::= TOKEN(B) TOKEN(C). {addTableDefNode(B, C); free(B); free(C);} diff --git a/src/sqsh_parser/tsql.yy.c b/src/sqsh_parser/tsql.yy.c new file mode 100644 index 0000000..0c30655 --- /dev/null +++ b/src/sqsh_parser/tsql.yy.c @@ -0,0 +1,2097 @@ +#line 2 "tsql.yy.c" + +#line 4 "tsql.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 17 +#define YY_END_OF_BUFFER 18 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_acclist[100] = + { 0, + 18, 15, 17, 16, 17, 15, 17, 15, 17, 15, + 17, 15, 17, 15, 17, 15, 17, 14, 15, 17, + 13, 15, 17, 7, 15, 17, 7, 15, 17, 7, + 15, 17, 7, 15, 17, 7, 15, 17, 7, 15, + 17, 7, 15, 17, 15, 17, 15, 17, 10, 15, + 17, 15, 17, 7, 7, 7, 7, 7,16390, 7, + 7, 7, 10, 8, 7, 7, 7, 8198, 7, 7, + 7, 9, 11, 12, 7, 7, 7,16389, 7, 7, + 7, 4, 1, 7,16389, 8197, 7,16389, 7,16389, + 7,16390,16386,16386,16386, 8194, 8194,16387, 8195 + + } ; + +static yyconst flex_int16_t yy_accept[100] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 2, 4, 6, + 8, 10, 12, 14, 16, 18, 21, 24, 27, 30, + 33, 36, 39, 42, 45, 47, 49, 52, 54, 54, + 54, 54, 54, 54, 54, 55, 56, 57, 58, 60, + 61, 62, 63, 63, 63, 64, 64, 64, 64, 64, + 64, 64, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 72, 73, 73, 74, 74, 75, 75, 75, 75, + 75, 75, 76, 77, 79, 80, 81, 82, 82, 82, + 83, 83, 84, 86, 87, 89, 91, 93, 94, 95, + 96, 97, 98, 98, 98, 98, 99, 100, 100 + + } ; + +static yyconst flex_int32_t yy_meta[257] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 4, 1, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, + 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 1, 6, 1, 5, 1, 5, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, + 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 1, 1, 1, 1, 1, 5, 1, 1, + 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 7 + } ; + +static yyconst flex_int16_t yy_base[110] = + { 0, + 0, 7, 115, 0, 301, 0, 161, 525, 525, 0, + 0, 0, 2, 46, 0, 525, 525, 0, 5, 5, + 2, 9, 3, 0, 0, 0, 0, 0, 10, 5, + 16, 22, 47, 123, 0, 13, 22, 26, 2, 13, + 27, 30, 63, 120, 0, 60, 63, 64, 56, 70, + 43, 117, 525, 67, 59, 54, 9, 70, 68, 59, + 57, 525, 114, 525, 0, 525, 58, 61, 11, 60, + 16, 63, 18, 23, 64, 63, 138, 139, 125, 29, + 142, 235, 237, 243, 245, 250, 252, 263, 276, 281, + 283, 289, 160, 165, 172, 291, 296, 525, 496, 3, + + 499, 2, 1, 501, 0, 505, 509, 514, 518 + } ; + +static yyconst flex_int16_t yy_def[110] = + { 0, + 99, 99, 99, 3, 99, 5, 98, 98, 98, 98, + 98, 98, 98, 98, 100, 98, 98, 101, 101, 101, + 101, 101, 101, 101, 102, 103, 104, 105, 98, 98, + 98, 98, 98, 106, 101, 101, 101, 101, 101, 101, + 101, 101, 107, 108, 104, 109, 98, 98, 98, 98, + 98, 106, 98, 101, 101, 101, 98, 101, 101, 101, + 107, 98, 108, 98, 109, 98, 98, 98, 98, 98, + 98, 101, 101, 101, 101, 101, 101, 98, 98, 98, + 98, 98, 101, 98, 101, 101, 101, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 0, 98, 98, + + 98, 98, 98, 98, 98, 98, 98, 98, 98 + } ; + +static yyconst flex_int16_t yy_nxt[782] = + { 0, + 98, 98, 98, 98, 46, 44, 43, 34, 98, 9, + 57, 57, 98, 98, 57, 98, 9, 57, 57, 80, + 80, 57, 98, 80, 82, 82, 80, 80, 82, 98, + 80, 84, 84, 57, 98, 84, 98, 80, 80, 98, + 57, 80, 80, 98, 98, 98, 98, 82, 98, 80, + 98, 98, 98, 98, 84, 98, 98, 98, 98, 98, + 80, 98, 98, 98, 98, 98, 98, 10, 29, 98, + 38, 42, 11, 12, 10, 41, 98, 30, 31, 11, + 12, 32, 36, 37, 13, 47, 39, 48, 49, 50, + 54, 13, 66, 40, 55, 56, 58, 59, 60, 10, + + 29, 14, 38, 42, 11, 12, 10, 41, 14, 30, + 31, 11, 12, 32, 36, 37, 13, 47, 39, 48, + 49, 50, 54, 13, 9, 40, 55, 56, 58, 59, + 60, 67, 68, 69, 70, 72, 73, 74, 75, 76, + 77, 78, 79, 81, 83, 85, 86, 64, 15, 62, + 53, 71, 66, 64, 16, 62, 53, 51, 17, 33, + 98, 98, 98, 67, 68, 69, 70, 72, 73, 74, + 75, 76, 77, 78, 79, 81, 83, 85, 86, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 20, 18, + 21, 18, 18, 22, 18, 18, 23, 18, 18, 18, + + 18, 24, 18, 18, 18, 25, 87, 88, 89, 18, + 90, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 20, 18, 21, 18, 18, 22, 18, 18, 23, 18, + 18, 18, 18, 24, 18, 18, 18, 94, 87, 88, + 89, 98, 90, 82, 82, 84, 84, 82, 95, 84, + 96, 84, 84, 84, 84, 84, 98, 84, 84, 84, + 57, 57, 84, 98, 57, 98, 82, 98, 84, 94, + 98, 91, 91, 18, 84, 91, 84, 98, 18, 98, + 95, 84, 96, 57, 92, 92, 98, 98, 92, 91, + 91, 91, 91, 91, 91, 91, 18, 92, 92, 97, + + 97, 92, 18, 97, 97, 97, 98, 92, 97, 18, + 9, 98, 91, 98, 91, 98, 98, 98, 98, 98, + 92, 98, 97, 98, 98, 98, 98, 97, 98, 98, + 98, 98, 98, 98, 26, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 93, 98, 98, 98, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 28, 98, 93, 98, 27, 98, 27, 27, 27, + + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 27, + 98, 98, 98, 98, 27, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 27, 98, 98, 98, 98, 98, 27, 98, + 98, 98, 98, 98, 98, 27, 8, 8, 8, 8, + + 8, 8, 35, 35, 45, 45, 52, 52, 52, 52, + 61, 98, 61, 61, 61, 63, 63, 63, 63, 65, + 98, 65, 65, 65, 7, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98 + } ; + +static yyconst flex_int16_t yy_chk[782] = + { 0, + 0, 0, 0, 0, 105, 103, 102, 100, 0, 1, + 39, 39, 0, 0, 39, 0, 2, 57, 57, 69, + 69, 57, 0, 69, 71, 71, 73, 73, 71, 0, + 73, 74, 74, 39, 0, 74, 0, 80, 80, 0, + 57, 80, 69, 0, 0, 0, 0, 71, 0, 73, + 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, + 80, 0, 0, 0, 0, 0, 0, 1, 10, 0, + 21, 24, 1, 1, 2, 23, 0, 11, 12, 2, + 2, 13, 19, 20, 1, 29, 22, 30, 31, 32, + 36, 2, 65, 22, 37, 38, 40, 41, 42, 1, + + 10, 1, 21, 24, 1, 1, 2, 23, 2, 11, + 12, 2, 2, 13, 19, 20, 1, 29, 22, 30, + 31, 32, 36, 2, 3, 22, 37, 38, 40, 41, + 42, 47, 48, 49, 50, 54, 55, 56, 58, 59, + 60, 67, 68, 70, 72, 75, 76, 63, 3, 61, + 52, 51, 46, 44, 3, 43, 34, 33, 3, 14, + 7, 0, 0, 47, 48, 49, 50, 54, 55, 56, + 58, 59, 60, 67, 68, 70, 72, 75, 76, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + + 3, 3, 3, 3, 3, 3, 77, 78, 79, 3, + 81, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 93, 77, 78, + 79, 0, 81, 82, 82, 83, 83, 82, 94, 83, + 95, 84, 84, 85, 85, 84, 0, 85, 86, 86, + 87, 87, 86, 0, 87, 0, 82, 0, 83, 93, + 0, 88, 88, 3, 84, 88, 85, 0, 3, 0, + 94, 86, 95, 87, 89, 89, 0, 0, 89, 90, + 90, 91, 91, 90, 88, 91, 3, 92, 92, 96, + + 96, 92, 3, 96, 97, 97, 0, 89, 97, 3, + 5, 0, 90, 0, 91, 0, 0, 0, 0, 0, + 92, 0, 96, 0, 0, 0, 0, 97, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 92, 0, 0, 0, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 0, 92, 0, 5, 0, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 5, 99, 99, 99, 99, + + 99, 99, 101, 101, 104, 104, 106, 106, 106, 106, + 107, 0, 107, 107, 107, 108, 108, 108, 108, 109, + 0, 109, 109, 109, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98 + } ; + +static yyconst yy_state_type yy_NUL_trans[98] = + { 0, + 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + + } ; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; +static char *yy_full_match; +static int yy_lp; +static int yy_looking_for_trail_begin = 0; +static int yy_full_lp; +static int *yy_full_state; +#define YY_TRAILING_MASK 0x2000 +#define YY_TRAILING_HEAD_MASK 0x4000 +#define REJECT \ +{ \ +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ +yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ +(yy_lp) = (yy_full_lp); /* restore orig. accepting pos. */ \ +(yy_state_ptr) = (yy_full_state); /* restore orig. state */ \ +yy_current_state = *(yy_state_ptr); /* restore curr. state */ \ +++(yy_lp); \ +goto find_rule; \ +} + +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "tsql.l" +#line 2 "tsql.l" +#include "tsql.h" + +#define KW(w) {return w;} + + + +#line 699 "tsql.yy.c" + +#define INITIAL 0 +#define INFROM 1 +#define INDML 2 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + unsigned n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 20 "tsql.l" + + +#line 886 "tsql.yy.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + /* Create the reject buffer large enough to save one state per allowed character. */ + if ( ! (yy_state_buf) ) + (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); + if ( ! (yy_state_buf) ) + YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); + + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + +yy_match: + do + { + register YY_CHAR yy_c = YY_SC_TO_UI(*yy_cp); + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 99 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *(yy_state_ptr)++ = yy_current_state; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 525 ); + +yy_find_action: + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ + for ( ; ; ) /* until we find what rule we matched */ + { + if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) + { + yy_act = yy_acclist[(yy_lp)]; + if ( yy_act & YY_TRAILING_HEAD_MASK || + (yy_looking_for_trail_begin) ) + { + if ( yy_act == (yy_looking_for_trail_begin) ) + { + (yy_looking_for_trail_begin) = 0; + yy_act &= ~YY_TRAILING_HEAD_MASK; + break; + } + } + else if ( yy_act & YY_TRAILING_MASK ) + { + (yy_looking_for_trail_begin) = yy_act & ~YY_TRAILING_MASK; + (yy_looking_for_trail_begin) |= YY_TRAILING_HEAD_MASK; + } + else + { + (yy_full_match) = yy_cp; + (yy_full_state) = (yy_state_ptr); + (yy_full_lp) = (yy_lp); + break; + } + ++(yy_lp); + goto find_rule; + } + --yy_cp; + yy_current_state = *--(yy_state_ptr); + (yy_lp) = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp = yy_bp + 4; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 22 "tsql.l" +{BEGIN INFROM; KW(FROM);} + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 23 "tsql.l" +{BEGIN INDML; KW(INSUP);} + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 24 "tsql.l" +{BEGIN INDML; KW(INSUP);} + YY_BREAK +case 4: +/* rule 4 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp = yy_bp + 4; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 25 "tsql.l" +{BEGIN INFROM; KW(JOIN);} + YY_BREAK +case 5: +/* rule 5 can match eol */ +YY_RULE_SETUP +#line 26 "tsql.l" +{BEGIN INITIAL;} + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 27 "tsql.l" +{BEGIN INITIAL;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 28 "tsql.l" +{KW(TOKEN);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 29 "tsql.l" +{KW(TOKEN);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 30 "tsql.l" +{KW(TOKEN);} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 31 "tsql.l" +{BEGIN INITIAL; KW(TOKEN);} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 32 "tsql.l" +{BEGIN INITIAL; KW(TOKEN);} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 33 "tsql.l" +{BEGIN INITIAL; KW(TOKEN);} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 34 "tsql.l" +{KW(COMMA);} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 35 "tsql.l" +{BEGIN INITIAL;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 36 "tsql.l" +; + YY_BREAK +case 16: +/* rule 16 can match eol */ +YY_RULE_SETUP +#line 37 "tsql.l" +; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 40 "tsql.l" +ECHO; + YY_BREAK +#line 1096 "tsql.yy.c" + case YY_STATE_EOF(INITIAL): + case YY_STATE_EOF(INFROM): + case YY_STATE_EOF(INDML): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + (yy_state_ptr) = (yy_state_buf); + *(yy_state_ptr)++ = yy_current_state; + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + if ( *yy_cp ) + { + register YY_CHAR yy_c = YY_SC_TO_UI(*yy_cp); + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 99 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + else + yy_current_state = yy_NUL_trans[yy_current_state]; + *(yy_state_ptr)++ = yy_current_state; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_NUL_trans[yy_current_state]; + yy_is_jam = (yy_current_state == 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + + (yy_state_buf) = 0; + (yy_state_ptr) = 0; + (yy_full_match) = 0; + (yy_lp) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + yyfree ( (yy_state_buf) ); + (yy_state_buf) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 40 "tsql.l" + + + +int testlex(char *buffer) +{ + yy_scan_string(buffer); + int rl; + + while ((rl=yylex())!=0){ + printf("Token: %i yytext: %s\n", rl, yytext); + } + yylex_destroy(); + return 0; +} + +extern void *ParseAlloc(void *(*mallocProc)(size_t)); +extern void ParseFree(void *p, void (*freeProc)(void*)); +extern void Parse(void *yyp, int yymajor, void* yyminor); +void parseSql(char* sql) { + int lr; + void* pParser = ParseAlloc(malloc); + + yy_scan_string(sql); + + while ((lr=yylex())!=0){ + Parse(pParser, lr, strdup(yytext)); + } + Parse(pParser, 0, NULL); + ParseFree(pParser, free); + yylex_destroy(); +} + diff --git a/src/sqsh_readline.c b/src/sqsh_readline.c index 2e351db..b16784a 100644 --- a/src/sqsh_readline.c +++ b/src/sqsh_readline.c @@ -24,32 +24,21 @@ */ #include <stdio.h> #include <ctype.h> +#include <regex.h> #include "sqsh_config.h" +#include "sqsh_env.h" #include "sqsh_error.h" +#include "sqsh_expand.h" /* sqsh-2.1.6 */ #include "sqsh_global.h" -#include "sqsh_env.h" -#include "sqsh_stdin.h" +#include "sqsh_init.h" #include "sqsh_readline.h" -#include "sqsh_expand.h" /* sqsh-2.1.6 */ - -#if defined(USE_READLINE) -#include <readline/readline.h> - -/* - * Readline history functions - for some reason not all - * readline installs have history.h available, so we do - * this. - */ -extern void stifle_history(); -extern int read_history(); -extern int write_history(); -extern void add_history(); - -#endif /* USE_READLINE */ +#include "sqsh_stdin.h" +#include "sqsh_varbuf.h" +#include "sqsh_parser/sqsh_parser.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: sqsh_readline.c,v 1.3 2009/04/14 10:41:33 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: sqsh_readline.c,v 1.14 2013/12/12 11:36:52 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -65,6 +54,18 @@ static char* sqsh_generator _ANSI_ARGS(( char*, int )) ; #endif /* + * sqsh-2.1.8 - Function prototypes for new feature column name completion. + */ +static int sqsh_readline_addcol _ANSI_ARGS(( char* )) ; +static int sqsh_readline_clearcol _ANSI_ARGS(( void )) ; +static int DynColnameLoad _ANSI_ARGS(( char*, char* )) ; + +/* + * sqsh-2.2.0 - Function prototypes for new feature readline_histignore. + */ +static int regex_match _ANSI_ARGS(( char*, char* )) ; + +/* * If GNU Readline support is compiled in, this data structure is * used to contain the active list of keywords. */ @@ -76,6 +77,14 @@ typedef struct keyword_st { /*-- Linked list of keywords --*/ static keyword_t *sg_keyword_start = NULL ; static keyword_t *sg_keyword_end = NULL ; +static keyword_t *sg_colname_start = NULL ; +static keyword_t *sg_colname_end = NULL ; + +/* + * sqsh-2.3 - Variable sg_rl_string points to varbuf buffer + * to prevent data overflows. +*/ +static varbuf_t *sg_rl_string = NULL ; #endif /* USE_READLINE */ @@ -105,6 +114,8 @@ int sqsh_readline_init() return True; } + DBG(sqsh_debug( DEBUG_READLINE, "sqsh_readline_init: Initializing\n" );) + /* * Set up the limit on the size of the readline history * buffer according to the value of $readline_history. @@ -136,16 +147,38 @@ int sqsh_readline_init() if (sqsh_expand (readline_history, exp_buf, 0) != False) read_history( varbuf_getstr(exp_buf) ); else - fprintf( stderr, "sqsh: Error expanding $readline_history: %s\n", - sqsh_get_errstr() ); + fprintf( stderr, "sqsh: Error expanding $readline_history: %s\n", sqsh_get_errstr() ); varbuf_destroy (exp_buf); } - DBG(sqsh_debug( DEBUG_READLINE, "sqsh_readline_init: Initializing\n" );) + /* + * sqsh-2.1.8: Moved loading keyword_file from sqsh_main.c to here. + * If the user has requested some form of keyword completion + * then attempt to read the contents of the keywords file. + */ + (void) sqsh_readline_load (); rl_readline_name = "sqsh" ; - rl_completion_entry_function = (rl_compentry_func_t*)sqsh_generator ; - rl_attempted_completion_function = (rl_completion_func_t *)sqsh_completion ; + rl_completion_entry_function = (rl_compentry_func_t *) sqsh_generator ; + rl_attempted_completion_function = (rl_completion_func_t *) sqsh_completion ; + + /* + * sqsh-2.1.8 - Remove '@' and '$' from the readline default list of word break + * characters by assigning a new list of word break characters to the variable + * rl_completer_word_break_characters. The @ and $ characters may be part + * of object/column names and would otherwise lead to problems with TAB completion + * when keyword_dynamic is enabled. + */ + rl_completer_word_break_characters = " \t\n\"\\'`><=;|&{("; + + /* + * sqsh-2.3 - Initialize variable sg_rl_string. + */ + if( (sg_rl_string = varbuf_create (16384)) == NULL ) { + sqsh_set_error( sqsh_get_error(), "sg_rl_string: %s", sqsh_get_errstr() ) ; + return False ; + } + #endif /* USE_READLINE */ return True ; @@ -186,6 +219,15 @@ int sqsh_readline_exit() sqsh_get_errstr() ); varbuf_destroy (exp_buf); } + + /* + * sqsh-2.3 - Cleanup sg_rl_string. + */ + if( sg_rl_string != NULL) { + varbuf_destroy ( sg_rl_string ); + sg_rl_string = NULL; + } + #endif /* USE_READLINE */ return True; @@ -200,77 +242,135 @@ int sqsh_readline_exit() char* sqsh_readline( prompt ) char *prompt; { - static char str[4096]; - char *line; + static char str[16384]; + #if defined(USE_READLINE) + char *line; char *cp; - /* sqsh-2.1.6 - New variables */ + /* sqsh-2.1.6 - New variable */ char *ignoreeof = NULL; + /* sqsh-2.2.0 - New variables */ + char *readline_histignore; + char *p1, *p2; + int match; + + sqsh_set_error( SQSH_E_NONE, NULL ); + if (prompt == NULL) + { + return ( sqsh_stdin_fgets( str, sizeof( str ) ) ); + } /* sqsh-2.1.6 feature - Expand color prompt */ prompt = expand_color_prompt (prompt, True); - if (prompt != NULL) + + /* + * sqsh-2.1.6 feature - Obtain environment variable ignoreeof. This will + * indicate if we have to ignore ^D yes or no. + */ + env_get( g_env, "ignoreeof", &ignoreeof ); + if (ignoreeof == NULL || *ignoreeof == '0') { /* - * sqsh-2.1.6 feature - Obtain environment variable ignoreeof. This will - * indicate if we have to ignore ^D yes or no. + * Standard behaviour: + * Since we have no way of capturing any real error conditions + * from readline, if it returns NULL we just have to assume + * that we have hit EOF, and not some error condition. From what + * we can tell from the readline library, there is no way to + * differentiate the two. */ - env_get( g_env, "ignoreeof", &ignoreeof ); - if (ignoreeof == NULL || *ignoreeof == '0') + if ((line = readline( prompt )) == NULL) { - /* - * Standard behaviour: - * Since we have no way of capturing any real error conditions - * from readline, if it returns NULL we just have to assume - * that we have hit EOF, and not some error condition. From what - * we can tell from the readline library, there is no way to - * differentiate the two. - */ - if ((line = readline( prompt )) == NULL) - { - sqsh_set_error( SQSH_E_NONE, NULL ); - return NULL; - } + return NULL; } - else - { - /* - ** If ignoreeof is defined True, continue with readline - ** as long as NULL is returned (accidentally C-d pressed). - */ - while ((line = readline( prompt )) == NULL) { - fprintf (stdout, "\nUse \"exit\" or \"quit\" to leave the sqsh shell.\n"); - fflush (stdout); - } + } + else + { + /* + ** If ignoreeof is defined True, continue with readline + ** as long as NULL is returned (accidentally C-d pressed). + */ + while ((line = readline( prompt )) == NULL) { + fprintf (stdout, "\nUse \"exit\" or \"quit\" to leave the sqsh shell.\n"); + fflush (stdout); } + } + /* + * Attempt to find out if there is anything in this line except + * for white-space. If there isn't then don't save it to the + * history. + */ + for (cp = line; *cp != '\0' && isspace((int)*cp); ++cp); + if (*cp != '\0') + { /* - * Attempt to find out if there is anything in this line except - * for white-space. If there isn't then don't save it to the - * history. - */ - for (cp = line; *cp != '\0' && isspace((int)*cp); ++cp); - - if (*cp != '\0') + * sqsh-2.2.0 - If $readline_histignore is set, then do not add the line to + * the readline history if it matches the provided regular expression or + * equals one of the colon separated list of keywords. + * if $readline_histignore starts with RE: then it is considered a regular + * expression that is evaluated with function regex_match. + * Rationale is to filter out the 'go', 'lo', 'mo', quit, etc. + * statements from the readline history. + */ + match = False; + env_get( g_env, "readline_histignore", &readline_histignore ); + if (readline_histignore != NULL && *readline_histignore != '\0') { - add_history( line ); - } - - /* - * Since readline mallocs line every time and doesn't append a - * newline, we make a copy of the current line, adding the newline - * and free the readline copy. - */ - sqsh_set_error( SQSH_E_NONE, NULL ); - sprintf( str, "%s\n", line ); - free( line ); + /* + * Duplicate the variable to a work buffer so we + * can modify it. What we want to do is strip of begin + * and end double quotes, if they exists. + */ + readline_histignore = sqsh_strdup (readline_histignore); + cp = readline_histignore; + if ( cp != NULL && *cp == '"' && *(cp+strlen(cp)-1) == '"' ) + { + *(cp+strlen(cp)-1) = '\0'; + cp = readline_histignore + 1; + } - return str; + if ( cp != NULL && strncmp (cp, "RE:", 3) == 0 ) + { + /* + * readline_histignore contains an extended regular expression + * if the string starts with RE: + */ + cp = cp + 3; + if (regex_match (cp, line) == 0) + match = True; + } + else + { + for (p1 = cp; p1 != NULL && match == False; p1 = p2) + { + if ( (p2 = strchr(p1, ':')) != NULL ) + *p2++ = '\0'; + if ( strcmp (line, p1) == 0 ) + match = True; + } + } + if ( readline_histignore != NULL ) + free (readline_histignore); + } + if ( match == False ) + add_history( line ); } -#endif + /* + * Since readline mallocs line every time and doesn't append a + * newline, we make a copy of the current line, adding the newline + * and free the readline copy. + * sqsh-2.3 - Use a flexible buffer instead of an array to store + * the line. This is to prevent data overflows. + */ + varbuf_strcpy ( sg_rl_string, line ); + varbuf_strcat ( sg_rl_string, "\n" ); + free( line ); + return (varbuf_getstr( sg_rl_string )); + +#else /* USE_READLINE */ /* * If the user supplied a prompt, then print it out. Otherwise @@ -286,15 +386,46 @@ char* sqsh_readline( prompt ) * Keep trying to read a line until we hit feof(stdin), or while * we are getting interrupted by signal handlers. */ - line = sqsh_stdin_fgets(str, sizeof( str )); + return ( sqsh_stdin_fgets( str, sizeof( str ))); - if (line == NULL) +#endif + +} + +/* + * sqsh_readline_load (): + * + * sqsh-2.1.8: Check and expand keyword_file variable and call sqsh_readline_read + * to suck in the keyword list. + */ +int sqsh_readline_load ( void ) +{ +#if !defined(USE_READLINE) + sqsh_set_error(SQSH_E_EXIST, "sqsh compiled without readline support" ) ; + return False ; +#else + char *keyword_file; + varbuf_t *exp_buf; + int ret = False ; + + env_get( g_env, "keyword_file", &keyword_file ); + if ( keyword_file != NULL && *keyword_file != '\0') { - return(NULL); + exp_buf = varbuf_create( 512 ); + if (exp_buf == NULL) + { + fprintf( stderr, "sqsh: %s\n", sqsh_get_errstr() ); + sqsh_exit( 255 ); + } + if (sqsh_expand( keyword_file, exp_buf, 0 ) != False) + ret = sqsh_readline_read( varbuf_getstr( exp_buf) ); + else + fprintf( stderr, "sqsh: Error expanding $keyword_file: %s\n", + sqsh_get_errstr() ); + varbuf_destroy( exp_buf ); } - - sqsh_set_error( SQSH_E_NONE, NULL ); - return line; + return ret; +#endif } /* @@ -331,7 +462,7 @@ int sqsh_readline_read( filename ) /*-- Skip whitespace --*/ while( ch != EOF && isspace((int)ch) ) ch = sqsh_getc(infile) ; - + idx = 0 ; while( ch != EOF && !(isspace((int)ch)) ) { keyword[idx++] = ch ; @@ -380,7 +511,7 @@ int sqsh_readline_add( keyword ) } k->k_nxt = NULL ; - DBG(sqsh_debug( DEBUG_READLINE, "sqsh_readline_add: Adding '%s'\n", + DBG(sqsh_debug( DEBUG_READLINE, "sqsh_readline_add: Adding '%s'\n", k->k_word ) ;) if( sg_keyword_end == NULL ) @@ -424,7 +555,7 @@ int sqsh_readline_clear() #if defined(USE_READLINE) /* - * This giant list is the complete list of key words avialable in + * This giant list is the complete list of key words avialable in * in Sybase System 10. It is used by the readline completion * generator function to do keyword completion. Note, this list * must remain in sorted order (case insensitive). @@ -434,245 +565,303 @@ int sqsh_readline_clear() * relatively useless for completion. Also, there are several * undocumented key words in here that aren't very useful to most * humans. + * sqsh-2.1.8 - Added all missing reserved words of ASE 15.7. */ static char *sqsh_statements[] = { "abs", "acos", - "add", - "all", - "alter", - "and", - "any", - "arith_overflow", - "as", - "asc", + "add", + "all", + "alter", + "and", + "any", + "arith_overflow", + "as", + "asc", "ascii", "asin", - "at", + "at", "atan", "atn2", - "authorization", - "avg", - "begin", - "between", - "break", - "browse", - "bulk", - "by", - "cascade", + "authorization", + "avg", + "begin", + "between", + "break", + "browse", + "bulk", + "by", + "cascade", + "case", "ceiling", "char", - "char_convert", + "char_convert", "char_length", "charindex", - "check", - "checkpoint", - "close", - "clustered", + "check", + "checkpoint", + "close", + "clustered", + "coalesce", "col_length", "col_name", - "commit", - "compute", - "confirm", - "constraint", - "continue", - "controlrow", - "convert", + "commit", + "compressed", + "compute", + "confirm", + "connect", + "constraint", + "continue", + "controlrow", + "convert", "cos", "cot", - "count", - "create", - "current", - "cursor", + "count", + "count_big", + "create", + "current", + "cursor", "curunreservedpgs", "data_pgs", - "database", + "database", "dateadd", "datediff", "datename", "datepart", "db_id", "db_name", - "dbcc", - "deallocate", - "declare", - "default", - "define", + "dbcc", + "deallocate", + "declare", + "decrypt", + "decrypt_default", + "default", + "define", "degrees", - "delete", - "desc", + "delete", + "desc", + "deterministic", "difference", - "disk", - "distinct", - "double", - "drop", - "dummy", - "dump", - "else", - "end", - "endtran", - "errlvl", - "errordata", - "errorexit", - "escape", - "except", - "execute", - "exists", - "exit", + "disk", + "distinct", + "double", + "drop", + "dual_control", + "dummy", + "dump", + "else", + "encrypt", + "end", + "endtran", + "errlvl", + "errordata", + "errorexit", + "escape", + "except", + "exclusive", + "exec", + "execute", + "exists", + "exit", "exp", - "fetch", - "fillfactor", + "exp_row_size", + "external", + "fetch", + "fillfactor", "floor", - "for", - "foreign", - "from", + "for", + "foreign", + "from", "getdate", - "goto", - "grant", - "group", - "having", + "goto", + "grant", + "group", + "having", "hextoint", - "holdlock", + "holdlock", "host_name", - "identity", - "identity_insert", - "if", - "in", - "index", + "identity", + "identity_gap", + "identity_insert", + "identity_start", + "if", + "in", + "index", "index_col", - "insert", - "intersect", - "into", + "inout", + "insensitive", + "insert", + "install", + "intersect", + "into", "inttohex", - "is", + "is", "isnull", - "isolation", - "key", - "kill", + "isolation", + "jar", + "join", + "key", + "kill", "lct_admin", - "level", - "like", - "lineno", - "load", - "log", + "level", + "like", + "lineno", + "load", + "lob_compression", + "lock", + "log", "log10", "lower", "ltrim", - "max", - "min", - "mirror", - "mirrorexit", - "national", - "noholdlock", - "nonclustered", - "not", - "null", - "numeric_truncation", + "materialized", + "max", + "max_rows_per_page", + "min", + "mirror", + "mirrorexit", + "modify", + "national", + "noholdlock", + "nonclustered", + "not", + "null", + "nullif", + "numeric_truncation", "object_id", "object_name", - "of", - "off", - "offsets", - "on", - "once", - "only", - "open", - "option", - "or", - "order", - "over", - "param", + "of", + "off", + "offsets", + "on", + "once", + "online", + "only", + "open", + "option", + "or", + "order", + "out", + "output", + "over", + "param", + "partition", "patindex", - "permanent", + "perm", + "permanent", "pi", - "plan", + "plan", "power", - "precision", - "prepare", - "primary", - "print", - "privileges", + "precision", + "prepare", + "primary", + "print", + "privileges", + "proc", "proc_role", - "procedure", - "processexit", - "public", + "procedure", + "processexit", + "proxy_table", + "public", + "quiesce", "radians", - "raiserror", + "raiserror", "rand", - "read", - "readtext", - "reconfigure", - "references", - "replace", + "read", + "readpast", + "readtext", + "reconfigure", + "references", + "release_locks_on_close", + "remove", + "reorg", + "replace", "replicate", + "replication", "reserved_pgs", - "restree", - "return", + "reservepagegap", + "restree", + "return", + "returns", "reverse", - "revoke", + "revoke", "right", - "role", - "rollback", + "role", + "rollback", "round", "rowcnt", - "rowcount", - "rows", + "rowcount", + "rows", "rtrim", - "rule", - "save", - "schema", - "select", - "set", - "setuser", - "shared", + "rule", + "save", + "schema", + "scroll", + "select", + "semi_sensitive", + "set", + "setuser", + "shared", "show_role", - "shutdown", + "shutdown", "sign", "sin", + "some", "soundex", "space", "sqrt", - "statement", - "statistics", + "statement", + "statistics", "str", - "stripe", + "stringsize", + "stripe", "stuff", "substring", - "sum", + "sum", "suser_id", "suser_name", - "syb_identity", - "table", + "syb_identity", + "syb_restree", + "syb_terminate", + "table", "tan", - "temporary", - "terminate", - "textsize", - "to", - "transaction", - "trigger", - "truncate", - "tsequal", - "union", - "unique", - "update", + "temp", + "temporary", + "terminate", + "textsize", + "to", + "tracefile", + "tran", + "transaction", + "trigger", + "truncate", + "tsequal", + "union", + "unique", + "unpartition", + "update", "upper", - "use", + "use", "used_pgs", - "user", + "user", "user_id", "user_name", - "user_option", - "using", + "user_option", + "using", "valid_name", - "values", - "varying", - "view", - "waitfor", - "where", - "while", - "with", - "work", - "writetext" + "values", + "varying", + "view", + "waitfor", + "when", + "where", + "while", + "with", + "work", + "writetext", + "xmlextract", + "xmlparse", + "xmltable", + "xmltest" } ; /* @@ -692,10 +881,14 @@ static char* sqsh_generator( text, state ) int low, high, middle; int len; int nitems; - int r; + int r; char *str; char *cptr; char *word; + char *keyword_dynamic; + char objname[256]; + varbuf_t *vb; + char *tn; len = strlen(text); nitems = sizeof(sqsh_statements) / sizeof(char*); @@ -706,7 +899,7 @@ static char* sqsh_generator( text, state ) * the user even wants statement completion. If he doesn't, then * don't do anything. */ - if (state == 0) + if (state == 0) { env_get( g_env, "keyword_completion", &keyword_completion ); @@ -714,10 +907,51 @@ static char* sqsh_generator( text, state ) return NULL; /* + * sqsh-2.1.8: In case keyword_dynamic is enabled, check if the user + * wants to autocomplete a column/parameter name. + */ + env_get( g_env, "keyword_dynamic", &keyword_dynamic ); + if (keyword_dynamic != NULL && *keyword_dynamic != '0') + { + /* + * sqsh-2.1.8: If the text string contains a dot, then assume the + * first part is an object name and the second part is the column + * name we want to autocomplete. Obtain the objname from the text + * and query all the column/parameter names for this object and + * store them in a linked list. + * sqsh-2.4 : Added code to generate a completion list for aliased + * objectnames as well. Code contributed by K.-M. Hansche. + */ + for ( idx = strlen(text)-1; idx >= 0 && text[idx] != '.'; idx-- ); + if ( idx >= 0 && text[idx] == '.' ) + { + strncpy ( objname, text, idx ); + objname[idx] = '\0'; + vb = varbuf_create ( varbuf_getlen(g_sqlbuf) + strlen(rl_line_buffer) ); + if (vb == NULL) + { + fprintf (stderr, "sqsh: %s\n", sqsh_get_errstr()); + sqsh_exit (255); + } + varbuf_strcpy ( vb, varbuf_getstr(g_sqlbuf) ); + varbuf_strcat ( vb, rl_line_buffer ); + + parseSql ( varbuf_getstr(vb) ); + tn = getTableForAlias ( objname ); + (void) DynColnameLoad ( (tn != NULL) ? tn : objname, objname ); + + varbuf_destroy(vb); + delTableDefs(); + } + else if (sg_colname_start != NULL) + sqsh_readline_clearcol (); + } + + /* * If the user has supplied their own keyword completion list * then we want to ignore the built-in one. */ - if (sg_keyword_start != NULL) + if ((sg_keyword_start != NULL) || (sg_colname_start != NULL)) { DBG(sqsh_debug(DEBUG_READLINE, "sqsh_generator: Using user list\n" );) @@ -725,7 +959,7 @@ static char* sqsh_generator( text, state ) * How's this for efficiency? A nice O(n) search of our list * of keywords. Ok, so it ain't so elegant. Sue me. */ - cur = sg_keyword_start; + cur = sg_colname_start != NULL ? sg_colname_start : sg_keyword_start; if (*keyword_completion == '4') /* Exact */ { for (; cur != NULL && strncmp( cur->k_word, text, len ) != 0; @@ -736,24 +970,29 @@ static char* sqsh_generator( text, state ) for (; cur != NULL && strncasecmp( cur->k_word, text, len ) != 0; cur = cur->k_nxt ); } - + /* * If we failed to find anything, then give up and return * NULL to the caller indicating that we are all done or * have not found a match. + * sqsh-2.5 : No results? Then try filename completion. */ if (cur == NULL) - return NULL; - + { + if (sg_colname_start != NULL) + sqsh_readline_clearcol(); + return ( rl_filename_completion_function (text, state) ); + } + /* * Otherwise, save a pointer to the word that matched * so that we can figure out what to do next. */ word = cur->k_word; - } + } else { - DBG(sqsh_debug(DEBUG_READLINE, + DBG(sqsh_debug(DEBUG_READLINE, "sqsh_generator: Using internal list\n" );) /* @@ -777,22 +1016,23 @@ static char* sqsh_generator( text, state ) } /* - * If we couldn't even find a partial match, then give up + * If we couldn't even find a partial match, then give up * and return NULL. + * sqsh-2.5 - Try filename completion instead. */ if (low > high) - return NULL; - + return( rl_filename_completion_function (text, state) ); + /* * Now, we have found an entry which matches (at least partially) * the value of text. However, we haven't necessarily found the - * first on in our sorted list, so we need to back up until we + * first on in our sorted list, so we need to back up until we * find it. */ for (idx = middle; idx > 0 && strncasecmp( sqsh_statements[idx-1], text, len ) == 0; --idx); - + word = sqsh_statements[idx]; } @@ -805,29 +1045,48 @@ static char* sqsh_generator( text, state ) * we want to traverse to the next item in the list and see * if it matches the partial text that was passed in. */ - if (sg_keyword_start != NULL) + if ((sg_keyword_start != NULL) || (sg_colname_start != NULL)) { /* * If we are already at the end of the list then don't * bother to return anything. + * sqsh-2.5 : Try filename completion instead. */ if (cur == NULL) - return NULL; + { + if (sg_colname_start != NULL) + sqsh_readline_clearcol(); + return( rl_filename_completion_function (text, state) ); + } /* - * Traverse on through the list until we find another + * Traverse on through the list until we find another * match or reach the end of the list. */ - for (cur = cur->k_nxt; - cur != NULL && strncasecmp( cur->k_word, text, len ) != 0; - cur = cur->k_nxt ); - + if (*keyword_completion == '4') /* Exact */ + { + for (cur = cur->k_nxt; + cur != NULL && strncmp( cur->k_word, text, len ) != 0; + cur = cur->k_nxt ); + } + else + { + for (cur = cur->k_nxt; + cur != NULL && strncasecmp( cur->k_word, text, len ) != 0; + cur = cur->k_nxt ); + } + /* * If we hit the end, then we let the caller know that * we are all done. + * sqsh-2.5 : Try filename completion instead. */ if (cur == NULL) - return NULL; + { + if (sg_colname_start != NULL) + sqsh_readline_clearcol(); + return( rl_filename_completion_function (text, state) ); + } word = cur->k_word; @@ -840,7 +1099,7 @@ static char* sqsh_generator( text, state ) */ ++idx; if (idx >= nitems || strncasecmp(sqsh_statements[idx],text,len) != 0) - return NULL; + return( rl_filename_completion_function (text, state) ); word = sqsh_statements[idx]; } } @@ -852,49 +1111,49 @@ static char* sqsh_generator( text, state ) * requested the 'keyword_completion' variable and return * it. */ - str = (char*)malloc( (strlen(word) + 1) * sizeof(char) ); - - if (str == NULL) + if ((str = (char*) malloc( (strlen(word) + 1) * sizeof(char) )) == NULL) { + if (sg_colname_start != NULL) + sqsh_readline_clearcol(); return NULL; } switch (*keyword_completion) { case '1': /* Lower case */ - + for (cptr = str; *word != '\0'; ++word, ++cptr) { - *cptr = tolower(*word); + *cptr = tolower( (int) *word); } *cptr = '\0'; break; - + case '2': /* Upper case */ for (cptr = str; *word != '\0'; ++word, ++cptr) { - *cptr = toupper(*word); + *cptr = toupper( (int) *word); } *cptr = '\0'; break; - + case '3': /* Smart */ for (cptr = str; *word != '\0'; ++word, ++cptr) { if (isupper((int)*text)) { - *cptr = toupper(*word); + *cptr = toupper( (int) *word); } else { - *cptr = tolower(*word); + *cptr = tolower( (int) *word); } } *cptr = '\0'; break; - + case '4': /* Exact */ default: strcpy( str, word ); @@ -911,4 +1170,244 @@ static char** sqsh_completion( text, start, end ) return (char **)rl_completion_matches( text, (rl_compentry_func_t*)sqsh_generator ) ; } + +/* + * sqsh-2.1.8 - New feature: dynamic column name completion. + * + * The next local functions implement the dynamic column name completion feature. + * To keep it simple, I just used my own copies of some of the above functions to + * distinguish them from the existing functions that are being used by the keyword + * completion function, instead of adapting these functions for generic use. + */ + + +/* + * sqsh_readline_addcol() + * + * sqsh-2.1.8: Add a new column name to the readline keyword completion list. + */ +static int sqsh_readline_addcol( keyword ) + char *keyword ; +{ + keyword_t *k ; + + /*-- Allocate a new structure --*/ + if( (k = (keyword_t*)malloc(sizeof(keyword_t))) == NULL ) { + sqsh_set_error( SQSH_E_NOMEM, NULL ) ; + return False ; + } + + /*-- Create the keyword --*/ + if( (k->k_word = sqsh_strdup( keyword )) == NULL ) { + free( k ) ; + sqsh_set_error( SQSH_E_NOMEM, NULL ) ; + return False ; + } + k->k_nxt = NULL ; + + DBG(sqsh_debug( DEBUG_READLINE, "sqsh_readline_add: Adding '%s'\n", + k->k_word ) ;) + + if( sg_colname_end == NULL ) + sg_colname_start = sg_colname_end = k ; + else { + sg_colname_end->k_nxt = k ; + sg_colname_end = k ; + } + + return True ; +} + + +/* + * sqsh_readline_clearcol(): + * + * sqsh-2.1.8: Clears the contents of the object specific column name linked list. + */ +static int sqsh_readline_clearcol() +{ + keyword_t *k, *n ; + + k = sg_colname_start ; + while( k != NULL ) { + n = k->k_nxt ; + free( k->k_word ) ; + free( k ) ; + k = n ; + } + + sg_colname_start = sg_colname_end = NULL ; + return True ; +} + + +/* + * Function: DynColnameLoad() + * + * sqsh-2.1.8 - Dynamically execute a query to obtain the column names of + * an existing table, view or stored procedure. + * sqsh-2.4 - Also take the database into account. An object may be + * specified as master.dbo.sysdatabases, or dbo.sysusages + * or syscolumns for example, the last two expected to + * exist in the current database. + * + */ +static int DynColnameLoad (objname, alias) + char *objname; + char *alias; +{ + CS_COMMAND *cmd; + CS_DATAFMT columns[1]; + CS_RETCODE ret; + CS_RETCODE results_ret; + CS_INT result_type; + CS_INT count; + CS_INT idx; + CS_INT datalength[1]; + CS_SMALLINT indicator [1]; + CS_CHAR name [256]; + CS_CHAR query [768]; + CS_CHAR dbname [256]; + char *cptr; + + + if (sg_colname_start != NULL) + { + sqsh_readline_clearcol(); + } + if ( g_connection == NULL ) + { + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: g_connection is not initialized.\n")); + return (CS_FAIL); + } + if (ct_cmd_alloc( g_connection, &cmd ) != CS_SUCCEED) + { + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Call to ct_cmd_alloc failed.\n")); + return (CS_FAIL); + } + /* + * sqsh-2.4 - If the objectname contains two dots, then the first part specifies + * the database name, the second part the owner name (may be empty) and the last + * part the objectname itself. + */ + if ((cptr = strchr( objname, '.' )) != NULL && strchr( cptr + 1, '.' ) != NULL) + { + idx = (CS_INT) (cptr - objname); + strncpy (dbname, objname, idx); + dbname[idx] = '\0'; + sprintf (query, "select \'%s.\' + name from %s..syscolumns where id=object_id(\'%s\') order by name" + ,alias, dbname, objname); + } + else + sprintf (query, "select \'%s.\' + name from syscolumns where id=object_id(\'%s\') order by name" + ,alias, objname); + + if (ct_command( cmd, /* Command Structure */ + CS_LANG_CMD, /* Command Type */ + query, /* Query Buffer */ + CS_NULLTERM, /* Buffer Length */ + CS_UNUSED /* Options */ + ) != CS_SUCCEED) + { + ct_cmd_drop( cmd ); + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Call to ct_command failed.\n")); + return (CS_FAIL); + } + if (ct_send( cmd ) != CS_SUCCEED) + { + ct_cmd_drop( cmd ); + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Call to ct_send failed.\n")); + return (CS_FAIL); + } + + while ((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED) + { + switch ((int) result_type) + { + case CS_ROW_RESULT: + columns[0].datatype = CS_CHAR_TYPE; + columns[0].format = CS_FMT_NULLTERM; + columns[0].maxlength = 255; + columns[0].count = 1; + columns[0].locale = NULL; + ct_bind(cmd, 1, &columns[0], name, &datalength[0], &indicator[0]); + + while (ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count) == CS_SUCCEED) + { + /* Remove trailing blanks, tabs and newlines, just in case */ + for ( idx = strlen(name) - 1; + idx >= 0 && (name[idx] == ' ' || name[idx] == '\t' || name[idx] == '\n'); + name[idx--] = '\0'); + + sqsh_readline_addcol ( name ); /* Add name to linked list of colnames */ + } + break; + + case CS_CMD_SUCCEED: + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: No rows returned from query.\n")); + ret = CS_FAIL; + break; + + case CS_CMD_FAIL: + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Error encountered during query processing.\n")); + ret = CS_FAIL; + break; + + case CS_CMD_DONE: + break; + + default: + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Unexpected error encountered. (1)\n")); + ret = CS_FAIL; + break; + } + } + + switch ((int) results_ret) + { + case CS_END_RESULTS: + ret = CS_SUCCEED; + break; + + case CS_FAIL: + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Unexpected error encountered. (2)\n")); + ret = CS_FAIL; + break; + + default: + DBG(sqsh_debug(DEBUG_ERROR, "DynColnameLoad: Unexpected error encountered. (3)\n")); + ret = CS_FAIL; + break; + } + ct_cmd_drop( cmd ); + if (ret == CS_FAIL) + sqsh_readline_clearcol(); + + return ( ret ); +} + + +/* + * sqsh-2.2.0 - Function regex_match. + * + * Match string against the extended regular expression in + * pattern, treating errors as no match. + * + * Return 0 for match, not 0 for no match. +*/ +static int regex_match (pattern, string) + char *pattern; + char *string; +{ + regex_t re; + int status; + + + if ((status = regcomp (&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE) != 0)) + return (status); + status = regexec (&re, string, (size_t) 0, NULL, 0); + regfree (&re); + return (status); +} + #endif /* USE_READLINE */ diff --git a/src/sqsh_readline.h b/src/sqsh_readline.h index 257b8da..ede5c90 100644 --- a/src/sqsh_readline.h +++ b/src/sqsh_readline.h @@ -25,12 +25,40 @@ #ifndef sqsh_readline_h_included #define sqsh_readline_h_included +#if defined(USE_READLINE) +#include <readline/readline.h> + +/* + * Readline history functions - for some reason not all + * readline installs have history.h available, so we do + * this. + */ +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif /* PARAMS */ + +extern void _rl_clear_screen PARAMS((void)); + +#if !defined (_HISTORY_H_) +extern void stifle_history PARAMS((int)); +extern int unstifle_history PARAMS((void)); +extern int read_history PARAMS((const char *)); +extern int write_history PARAMS((const char *)); +extern void add_history PARAMS((const char *)); +#endif /*_HISTORY_H_ */ + +#endif /* USE_READLINE */ + /*-- Prototypes --*/ int sqsh_readline_init _ANSI_ARGS(( void )); int sqsh_readline_exit _ANSI_ARGS(( void )); char* sqsh_readline _ANSI_ARGS(( char* )) ; +int sqsh_readline_load _ANSI_ARGS(( void )) ; int sqsh_readline_read _ANSI_ARGS(( char* )) ; int sqsh_readline_add _ANSI_ARGS(( char* )) ; int sqsh_readline_clear _ANSI_ARGS(( void )) ; - #endif /* sqsh_readline_h_included */ @@ -60,6 +60,10 @@ int var_set_bcp_colsep _ANSI_ARGS(( env_t*, char*, char** )) ; int var_set_bcp_rowsep _ANSI_ARGS(( env_t*, char*, char** )) ; int var_set_bcp_trim _ANSI_ARGS(( env_t*, char*, char** )) ; int var_set_maxlen _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_set_datefmt _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_set_timefmt _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_set_lconv _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_set_p2fname _ANSI_ARGS(( env_t*, char*, char** )) ; /*-- Retrieval validation functions --*/ int var_get_date _ANSI_ARGS(( env_t*, char*, char** )) ; @@ -78,6 +82,8 @@ int var_get_bcp_rowsep _ANSI_ARGS(( env_t*, char*, char** )) ; int var_get_bcp_trim _ANSI_ARGS(( env_t*, char*, char** )) ; int var_get_interactive _ANSI_ARGS(( env_t*, char*, char** )) ; int var_get_maxlen _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_get_datefmt _ANSI_ARGS(( env_t*, char*, char** )) ; +int var_get_timefmt _ANSI_ARGS(( env_t*, char*, char** )) ; #ifdef SQSH_INIT @@ -100,13 +106,13 @@ static var_entry_t sg_var_entry[] = { { "banner", "1", var_set_bool, NULL }, { "batch_failcount", "0", var_set_add, NULL }, { "batch_pause", "0", var_set_bool, NULL }, - { "bcp_colsep", NULL, var_set_bcp_colsep, var_get_bcp_colsep}, - { "bcp_rowsep", NULL, var_set_bcp_rowsep, var_get_bcp_rowsep}, - { "bcp_trim", NULL, var_set_bcp_trim, var_get_bcp_trim}, - { "chained", NULL, var_set_bool, NULL }, /* XXX */ + { "bcp_colsep", "|", var_set_bcp_colsep, var_get_bcp_colsep}, + { "bcp_rowsep", "|", var_set_bcp_rowsep, var_get_bcp_rowsep}, + { "bcp_trim", "1", var_set_bcp_trim, var_get_bcp_trim}, + { "chained", NULL, var_set_bool, NULL }, { "charset", NULL, var_set_nullstr, NULL }, { "clear_on_fail", "1", var_set_bool, NULL }, - { "colsep", NULL, var_set_colsep, var_get_colsep }, + { "colsep", " ", var_set_colsep, var_get_colsep }, { "colwidth", "32", var_set_colwidth, var_get_colwidth}, { "DISPLAY", NULL, var_set_env, var_get_env }, { "database", NULL, var_set_nullstr, NULL }, @@ -124,51 +130,50 @@ static var_entry_t sg_var_entry[] = { { "footers", "1", var_set_bool, NULL }, { "headers", "1", var_set_bool, NULL }, { "help_dir", SQSH_HELP, var_set_path_r, NULL }, - { "history", SQSH_HISTORY, NULL, NULL }, + { "history", SQSH_HISTORY, var_set_nullstr, NULL }, { "history_shorthand","0", var_set_bool, NULL }, { "histnum", "0", var_set_int, NULL }, { "histsave", "1", var_set_bool, NULL }, { "histsize", "10", var_set_histsize, NULL }, { "hostname", NULL, var_set_nullstr, NULL }, { "ifs", "\n\f\r\t\v", var_set_esc, NULL }, - { "interactive", "1", NULL, var_get_interactive }, - { "interfaces", NULL, var_set_interfaces, NULL }, + { "interactive", "1", var_set_readonly, var_get_interactive }, + { "interfaces", NULL, var_set_interfaces, NULL }, { "keyword_completion", "0", var_set_completion, NULL }, - { "keyword_file", SQSH_WORDS, NULL, NULL }, + { "keyword_file", SQSH_WORDS, var_set_nullstr, NULL }, { "language", NULL, var_set_nullstr, NULL }, { "lineno", "1", var_set_add, NULL }, - { "linesep", NULL, var_set_linesep, var_get_linesep }, + { "linesep", "\n\t", var_set_linesep, var_get_linesep }, { "lock", NULL, var_set_lock, NULL }, - { "maxlen", NULL, var_set_maxlen, var_get_maxlen }, + { "maxlen", "32768", var_set_maxlen, var_get_maxlen }, { "newline_go", "0", var_set_bool, NULL }, { "output_parms", "1", var_set_outputparms, var_get_outputparms }, { "packet_size", NULL, var_set_packet, NULL }, { "password", "", var_set_password, NULL }, { "password_retry", "1", var_set_bool, NULL }, - { "prompt", "\\\\${lineno}> ",NULL, NULL }, - { "prompt2", "\\\\${lineno}--> ",NULL, NULL }, - { "rcfile", SQSH_RC, NULL, NULL }, - { "repeat_batch", "0", var_set_bool, NULL }, - { "readline_history",SQSH_RLHISTORY, NULL, NULL }, + { "prompt", "\\\\${lineno}> ",var_set_nullstr, NULL }, + { "prompt2", "\\\\${lineno}--> ",var_set_nullstr, NULL }, + { "rcfile", SQSH_RC, var_set_nullstr, NULL }, + { "repeat_batch", "0", var_set_bool, NULL }, + { "readline_history",SQSH_RLHISTORY, var_set_nullstr, NULL }, { "readline_histsize","100", var_set_rl_histsize, NULL }, - { "semicolon_hack", "0", var_set_bool, NULL }, - { "semicolon_cmd", "\\go", var_set_nullstr, NULL }, + { "semicolon_hack", "0", var_set_bool, NULL }, + { "semicolon_cmd", "\\go", var_set_nullstr, NULL }, { "session", SQSH_SESSION, var_set_nullstr, NULL }, - { "start_connected", "1", var_set_bool, NULL }, - { "statistics", "0", var_set_bool, NULL }, - { "style", "horiz", var_set_style, var_get_style }, - { "thresh_display", "0", var_set_severity, NULL }, - { "thresh_exit", "0", var_set_int, NULL }, - { "thresh_fail", "11", var_set_severity, NULL }, - { "tmp_dir", SQSH_TMP, NULL, NULL }, - { "username", NULL, NULL, NULL }, + { "statistics", "0", var_set_bool, NULL }, + { "style", "horizontal", var_set_style, var_get_style }, + { "thresh_display", "0", var_set_severity, NULL }, + { "thresh_exit", "0", var_set_int, NULL }, + { "thresh_fail", "11", var_set_severity, NULL }, + { "tmp_dir", SQSH_TMP, var_set_nullstr, NULL }, + { "username", NULL, var_set_nullstr, NULL }, { "version", SQSH_VERSION, var_set_readonly, NULL }, { "width", NULL, var_set_width, var_get_width }, { "xgeom", NULL, var_set_xgeom, var_get_xgeom }, { "date", "%d-%b-%y", var_set_notempty, var_get_date }, { "time", "%H:%M:%S", var_set_notempty, var_get_time }, /* sqsh-2.1.6 - New variables */ - { "appname", "sqsh-2.1.7", var_set_nullstr, NULL }, + { "appname", SQSH_VERSION, var_set_nullstr, NULL }, { "histunique", "0", var_set_bool, NULL }, { "ignoreeof", "0", var_set_bool, NULL }, { "login_timeout", NULL, var_set_nullint, NULL }, @@ -183,6 +188,35 @@ static var_entry_t sg_var_entry[] = { { "hist_auto_save", "0", var_set_int, NULL }, { "xwin_title", NULL, var_set_nullstr, NULL }, { "term_title", NULL, var_set_nullstr, NULL }, +#if defined(USE_READLINE) + /* sqsh-2.1.8 - New variables */ + { "keyword_dynamic", "0", var_set_bool, NULL }, + { "keyword_query", SQSH_KEYQUERY, var_set_nullstr, NULL }, +#endif + /* 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 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 }, + { "script", NULL, var_set_nullstr, NULL }, + { "semicolon_hack2", "0", var_set_bool, NULL }, + { "tds_version", NULL, var_set_nullstr, NULL }, + /* sqsh-2.3 - New variable */ + { "localeconv", "0", var_set_lconv, NULL }, + /* sqsh-2.4 - New variable */ + { "usedbcheck", "0", var_set_bool, NULL }, + /* sqsh-2.5 - New variables */ + { "nosepline", "0", var_set_bool, NULL }, + { "p2faxm", NULL, var_set_nullint, NULL }, + { "p2fname", NULL, var_set_p2fname, NULL }, +#if defined(__ansi__) + { "builddate", __DATE__, var_set_readonly, NULL }, + { "buildtime", __TIME__, var_set_readonly, NULL }, +#endif } ; #endif /* SQSH_INIT */ diff --git a/src/var_ctlib.c b/src/var_ctlib.c index d84abb3..c9384cb 100644 --- a/src/var_ctlib.c +++ b/src/var_ctlib.c @@ -34,7 +34,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_ctlib.c,v 1.2 2009/04/14 10:22:18 mwesdorp Exp $" ; +static char RCS_Id[] = "$Id: var_ctlib.c,v 1.3 2013/12/24 13:23:19 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -107,12 +107,15 @@ int var_set_packet( env, var_name, var_value ) return False; } + if (*var_value == NULL) + return True; + packet_size = atoi(*var_value); if (packet_size <= 0 || (packet_size % 512) != 0) { sqsh_set_error( SQSH_E_INVAL, - "Invalid packet size. Must a multiple of 512 bytes" ); + "Invalid packet size. Must be a multiple of 512 bytes" ); return False; } diff --git a/src/var_debug.c b/src/var_debug.c index 60ef639..cac311c 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.1.1.1 2004/04/07 12:35:03 chunkm0nkey Exp $" ; +static char RCS_Id[] = "$Id: var_debug.c,v 1.5 2014/03/12 14:40:42 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -55,6 +55,8 @@ struct debug_st { { "ERROR", DEBUG_ERROR }, { "EXPAND", DEBUG_EXPAND }, { "FD", DEBUG_FD }, + { "HISTORY", DEBUG_HISTORY }, + { "HIST", DEBUG_HISTORY }, { "JOB", DEBUG_JOB }, { "READLINE", DEBUG_READLINE}, { "RL", DEBUG_READLINE}, @@ -63,6 +65,7 @@ struct debug_st { { "SIG", DEBUG_SIG }, { "SIGCHLD", DEBUG_SIGCLD }, { "SIGCLD", DEBUG_SIGCLD }, + { "TDS", DEBUG_TDS }, } ; #endif @@ -91,7 +94,7 @@ int var_set_debug( env, var_name, var_value ) int nitems ; char error_msg[256]; - if( *var_value == NULL || strcmp(*var_value, "NULL") == 0 ) { + if( *var_value == NULL || strcasecmp(*var_value, "NULL") == 0 ) { sqsh_debug_level( 0 ) ; *var_value="0" ; return True ; @@ -103,17 +106,17 @@ int var_set_debug( env, var_name, var_value ) while( *str != '\0' ) { /*-- Skip leading white space --*/ - for( ; *str != '\0' && isspace(*str); ++str ) ; + for( ; *str != '\0' && isspace( (int) *str); ++str ) ; - for( i = 0; *str != '\0' && !(isspace(*str)) && *str != '|'; ++str ) { + for( i = 0; *str != '\0' && !(isspace( (int) *str)) && *str != '|'; ++str ) { if( i < sizeof(flag_name) ) flag_name[i++] = *str ; } flag_name[i] = '\0' ; - if( isspace(*str) ) { + if( isspace( (int) *str) ) { /*-- Skip leading white space --*/ - for( ++str; *str != '\0' && isspace(*str); ++str ) ; + for( ++str; *str != '\0' && isspace( (int) *str); ++str ) ; if( !(*str == '\0' || *str == '|') ) { sqsh_set_error( SQSH_E_INVAL, @@ -125,7 +128,7 @@ int var_set_debug( env, var_name, var_value ) if( *str != '\0' ) ++str ; - if( isdigit(*flag_name) ) + if( isdigit( (int) *flag_name) ) debug_flags |= atoi(flag_name) ; else { for( i = 0; i < nitems; i++ ) { diff --git a/src/var_dsp.c b/src/var_dsp.c index a3fb678..4dffb47 100644 --- a/src/var_dsp.c +++ b/src/var_dsp.c @@ -34,7 +34,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_dsp.c,v 1.3 2009/12/23 12:47:46 mwesdorp Exp $"; +static char RCS_Id[] = "$Id: var_dsp.c,v 1.7 2014/03/12 14:40:43 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -80,36 +80,24 @@ int var_set_fltfmt( env, var_name, var_value ) if (strcmp( var_name, "float" ) == 0) { - if (dsp_prop( DSP_SET, - DSP_FLOAT_PREC, - (void*)&prec, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_FLOAT_PREC, (void*)&prec, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - if (dsp_prop( DSP_SET, - DSP_FLOAT_SCALE, - (void*)&scale, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_FLOAT_SCALE, (void*)&scale, DSP_UNUSED ) != DSP_SUCCEED) { return False; } } else { - if (dsp_prop( DSP_SET, - DSP_REAL_PREC, - (void*)&prec, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_REAL_PREC, (void*)&prec, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - if (dsp_prop( DSP_SET, - DSP_REAL_SCALE, - (void*)&scale, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_REAL_SCALE, (void*)&scale, DSP_UNUSED ) != DSP_SUCCEED) { return False; } @@ -118,15 +106,20 @@ int var_set_fltfmt( env, var_name, var_value ) return True; } +/* + * sqsh-2.1.9 - Implement date and time datatype conversion routines. + * New and modified functions: var_set_datetime, var_get_datetime, + * var_set_datefmt, var_get_datefmt, var_set_timefmt, var_get_timefmt. + */ int var_set_datetime( env, var_name, var_value ) env_t *env ; char *var_name ; char **var_value ; { - if (dsp_prop( DSP_SET, - DSP_DATEFMT, - (void*)(*(var_value)), - DSP_NULLTERM ) != DSP_SUCCEED) + if ( *var_value == NULL || strcasecmp( *var_value, "NULL" ) == 0 || **var_value == '\0' ) + *var_value = NULL ; + + if (dsp_prop( DSP_SET, DSP_DATETIMEFMT, (void*)(*(var_value)), DSP_NULLTERM ) != DSP_SUCCEED) { return False; } @@ -141,10 +134,71 @@ int var_get_datetime( env, var_name, var_value ) { static char date_str[64]; - if (dsp_prop( DSP_GET, - DSP_DATEFMT, - (void*)date_str, - sizeof(date_str) ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_DATETIMEFMT, (void*)date_str, sizeof(date_str) ) != DSP_SUCCEED) + { + return False; + } + + *var_value = date_str; + return True; +} + +int var_set_datefmt( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + if ( *var_value == NULL || strcasecmp( *var_value, "NULL" ) == 0 || **var_value == '\0' ) + *var_value = NULL ; + + if (dsp_prop( DSP_SET, DSP_DATEFMT, (void*)(*(var_value)), DSP_NULLTERM ) != DSP_SUCCEED) + { + return False; + } + + return True; +} + +int var_get_datefmt( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + static char date_str[64]; + + if (dsp_prop( DSP_GET, DSP_DATEFMT, (void*)date_str, sizeof(date_str) ) != DSP_SUCCEED) + { + return False; + } + + *var_value = date_str; + return True; +} + +int var_set_timefmt( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + if ( *var_value == NULL || strcasecmp( *var_value, "NULL" ) == 0 || **var_value == '\0' ) + *var_value = NULL ; + + if (dsp_prop( DSP_SET, DSP_TIMEFMT, (void*)(*(var_value)), DSP_NULLTERM ) != DSP_SUCCEED) + { + return False; + } + + return True; +} + +int var_get_timefmt( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + static char date_str[64]; + + if (dsp_prop( DSP_GET, DSP_TIMEFMT, (void*)date_str, sizeof(date_str) ) != DSP_SUCCEED) { return False; } @@ -158,7 +212,7 @@ int var_set_style( env, var_name, var_value ) char *var_name; char **var_value; { - int dsp_style; + int style; if (*var_value == NULL) { @@ -170,36 +224,36 @@ int var_set_style( env, var_name, var_value ) strcmp( *var_value, "horiz" ) == 0 || strcmp( *var_value, "horizontal" ) == 0) { - dsp_style = DSP_HORIZ; + style = DSP_HORIZ; } else if (strcmp( *var_value, "vert" ) == 0 || strcmp( *var_value, "vertical" ) == 0) { - dsp_style = DSP_VERT; + style = DSP_VERT; } else if (strcmp( *var_value, "bcp" ) == 0) { - dsp_style = DSP_BCP; + style = DSP_BCP; } else if (strcmp( *var_value, "csv" ) == 0) { - dsp_style = DSP_CSV; + style = DSP_CSV; } else if (strcmp( *var_value, "html" ) == 0) { - dsp_style = DSP_HTML; + style = DSP_HTML; } else if (strcmp( *var_value, "none" ) == 0) { - dsp_style = DSP_NONE; + style = DSP_NONE; } else if (strcmp( *var_value, "meta" ) == 0) { - dsp_style = DSP_META; + style = DSP_META; } else if (strcmp( *var_value, "pretty" ) == 0) { - dsp_style = DSP_PRETTY; + style = DSP_PRETTY; } else { @@ -207,14 +261,13 @@ int var_set_style( env, var_name, var_value ) return False; } - if (dsp_prop( DSP_SET, - DSP_STYLE, - (void*)&dsp_style, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_STYLE, (void*)&style, DSP_UNUSED ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_style: Display style now set to %s\n", *var_value);) + return True; } @@ -223,17 +276,14 @@ int var_get_style( env, var_name, var_value ) char *var_name; char **var_value; { - int dsp_style; + int style; - if (dsp_prop( DSP_GET, - DSP_STYLE, - (void*)&dsp_style, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_STYLE, (void*)&style, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - switch (dsp_style) + switch (style) { case DSP_HORIZ: *var_value = "horizontal"; @@ -272,29 +322,45 @@ int var_set_colwidth( env, var_name, var_value ) char *var_name; char **var_value; { - int width; + int colwidth; if (var_set_nullint( env, var_name, var_value ) == False) { return False; } - width = atoi(*var_value); + colwidth = (*var_value != NULL) ? atoi(*var_value) : 30; - if (dsp_prop( DSP_SET, - DSP_COLWIDTH, - (void*)&width, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_COLWIDTH, (void*)&colwidth, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - DBG(sqsh_debug(DEBUG_SCREEN,"var_set_colwidth: Column width now set to %s\n", - *var_value);) + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_colwidth: Column width now set to %s\n", *var_value);) return True ; } +int var_get_colwidth( env, var_name, var_value ) + env_t *env; + char *var_name; + char **var_value; +{ + static char nbr[16]; + int colwidth; + + if (dsp_prop( DSP_GET, DSP_COLWIDTH, (void*)&colwidth, DSP_UNUSED ) != DSP_SUCCEED) + { + *var_value = NULL; + return False; + } + + sprintf( nbr, "%d", colwidth ); + + *var_value = nbr; + return True; +} + int var_set_outputparms( env, var_name, var_value ) env_t *env; char *var_name; @@ -309,17 +375,12 @@ int var_set_outputparms( env, var_name, var_value ) outputparms = atoi(*var_value); - if (dsp_prop( DSP_SET, - DSP_OUTPUTPARMS, - (void*)&outputparms, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_OUTPUTPARMS, (void*)&outputparms, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - DBG(sqsh_debug(DEBUG_SCREEN, - "var_set_output_parms: Column width now set to %s\n", - *var_value);) + DBG(sqsh_debug(DEBUG_SCREEN, "var_set_output_parms: Output parameters now set to %s\n", *var_value);) return True; } @@ -332,10 +393,7 @@ int var_get_outputparms( env, var_name, var_value ) static char nbr[4]; int outputparms; - if (dsp_prop( DSP_GET, - DSP_OUTPUTPARMS, - (void*)&outputparms, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_OUTPUTPARMS, (void*)&outputparms, DSP_UNUSED ) != DSP_SUCCEED) { *var_value = NULL; return False; @@ -359,18 +417,14 @@ int var_set_width( env, var_name, var_value ) return False; } - width = atoi(*var_value); + width = (*var_value != NULL) ? atoi(*var_value) : 0; - if (dsp_prop( DSP_SET, - DSP_WIDTH, - (void*)&width, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_WIDTH, (void*)&width, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - DBG(sqsh_debug(DEBUG_SCREEN,"var_set_width: Width now set to %s\n", - *var_value);) + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_width: Width now set to %s\n", *var_value);) return True ; } @@ -383,33 +437,7 @@ int var_get_width( env, var_name, var_value ) static char nbr[16]; int width; - if (dsp_prop( DSP_GET, - DSP_WIDTH, - (void*)&width, - DSP_UNUSED ) != DSP_SUCCEED) - { - *var_value = NULL; - return False; - } - - sprintf( nbr, "%d", width ); - - *var_value = nbr; - return True; -} - -int var_get_colwidth( env, var_name, var_value ) - env_t *env; - char *var_name; - char **var_value; -{ - static char nbr[16]; - int width; - - if (dsp_prop( DSP_GET, - DSP_COLWIDTH, - (void*)&width, - DSP_UNUSED ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_WIDTH, (void*)&width, DSP_UNUSED ) != DSP_SUCCEED) { *var_value = NULL; return False; @@ -426,19 +454,18 @@ int var_set_colsep( env, var_name, var_value ) char *var_name; char **var_value; { - if (var_set_nullstr( env, var_name, var_value ) == False) + if (var_set_esc( env, var_name, var_value ) == False) { return False; } - if (dsp_prop( DSP_SET, - DSP_COLSEP, - (void*)(*var_value), - DSP_NULLTERM ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_COLSEP, (void*)(*var_value), DSP_NULLTERM ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_colsep: Column separator now set to %s\n", *var_value);) + return True ; } @@ -449,10 +476,7 @@ int var_get_colsep( env, var_name, var_value ) { static char colsep[32]; - if (dsp_prop( DSP_GET, - DSP_COLSEP, - (void*)colsep, - sizeof(colsep) ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_COLSEP, (void*)colsep, sizeof(colsep) ) != DSP_SUCCEED) { *var_value = NULL; return False; @@ -467,17 +491,18 @@ int var_set_bcp_colsep( env, var_name, var_value ) char *var_name; char **var_value; { - if (var_set_nullstr( env, var_name, var_value ) == False) + if (var_set_esc( env, var_name, var_value ) == False) { return False; } - if (dsp_prop( DSP_SET, DSP_BCP_COLSEP, (void*)(*var_value), DSP_NULLTERM ) - != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_BCP_COLSEP, (void*)(*var_value), DSP_NULLTERM ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_bcp_colsep: BCP column separator now set to %s\n", *var_value);) + return True ; } @@ -486,16 +511,15 @@ int var_get_bcp_colsep( env, var_name, var_value ) char *var_name; char **var_value; { - static char colsep[32]; + static char bcp_colsep[32]; - if (dsp_prop( DSP_GET, DSP_BCP_COLSEP, (void*)colsep, sizeof(colsep) ) - != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_BCP_COLSEP, (void*)bcp_colsep, sizeof(bcp_colsep) ) != DSP_SUCCEED) { *var_value = NULL; return False; } - *var_value = colsep; + *var_value = bcp_colsep; return True ; } @@ -504,17 +528,18 @@ int var_set_bcp_rowsep( env, var_name, var_value ) char *var_name; char **var_value; { - if (var_set_nullstr( env, var_name, var_value ) == False) + if (var_set_esc( env, var_name, var_value ) == False) { return False; } - if (dsp_prop( DSP_SET, DSP_BCP_ROWSEP, (void*)(*var_value), DSP_NULLTERM ) - != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_BCP_ROWSEP, (void*)(*var_value), DSP_NULLTERM ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_bcp_rowsep: BCP row separator now set to %s\n", *var_value);) + return True ; } @@ -523,16 +548,15 @@ int var_get_bcp_rowsep( env, var_name, var_value ) char *var_name; char **var_value; { - static char rowsep[32]; + static char bcp_rowsep[32]; - if (dsp_prop( DSP_GET, DSP_BCP_ROWSEP, (void*)rowsep, sizeof(rowsep) ) - != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_BCP_ROWSEP, (void*)bcp_rowsep, sizeof(bcp_rowsep) ) != DSP_SUCCEED) { *var_value = NULL; return False; } - *var_value = rowsep; + *var_value = bcp_rowsep; return True ; } @@ -541,7 +565,7 @@ int var_set_bcp_trim( env, var_name, var_value ) char *var_name; char **var_value; { - int trim; + int bcp_trim; if (var_set_bool( env, var_name, var_value ) == False) { @@ -551,19 +575,20 @@ int var_set_bcp_trim( env, var_name, var_value ) /* MW: Applied fix from patch 2061950 by Klaus-Martin Hansche. */ if (strcmp(*var_value , "1") == 0) { - trim = True; + bcp_trim = True; } else { - trim = False; + bcp_trim = False; } - if (dsp_prop( DSP_SET, DSP_BCP_TRIM, (void*)&trim, DSP_UNUSED ) - != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_BCP_TRIM, (void*)&bcp_trim, DSP_UNUSED ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_bcp_trim: BCP trim now set to %s\n", *var_value);) + return True ; } @@ -572,15 +597,14 @@ int var_get_bcp_trim( env, var_name, var_value ) char *var_name; char **var_value; { - int trim; + int bcp_trim; - if (dsp_prop( DSP_GET, DSP_BCP_TRIM, (void*)&trim, DSP_UNUSED ) - != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_BCP_TRIM, (void*)&bcp_trim, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - if (trim == True) + if (bcp_trim == True) { *var_value = "1"; } @@ -596,19 +620,18 @@ int var_set_linesep( env, var_name, var_value ) char *var_name; char **var_value; { - if (var_set_nullstr( env, var_name, var_value ) == False) + if (var_set_esc( env, var_name, var_value ) == False) { return False; } - if (dsp_prop( DSP_SET, - DSP_LINESEP, - (void*)(*var_value), - DSP_NULLTERM ) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_LINESEP, (void*)(*var_value), DSP_NULLTERM ) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_linesep: Line separator now set to %s\n", *var_value);) + return True ; } @@ -619,10 +642,7 @@ int var_get_linesep( env, var_name, var_value ) { static char linesep[32]; - if (dsp_prop( DSP_GET, - DSP_LINESEP, - (void*)linesep, - sizeof(linesep) ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_LINESEP, (void*)linesep, sizeof(linesep) ) != DSP_SUCCEED) { *var_value = NULL; return False; @@ -673,14 +693,13 @@ int var_set_xgeom( env, var_name, var_value ) return False; } - if (dsp_prop( DSP_SET, - DSP_XGEOM, - (void*)(*var_value), - DSP_NULLTERM) != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_XGEOM, (void*)(*var_value), DSP_NULLTERM) != DSP_SUCCEED) { return False; } + DBG(sqsh_debug(DEBUG_SCREEN,"var_set_xgeom: Xgeom now set to %s\n", *var_value);) + return True; } @@ -691,10 +710,7 @@ int var_get_xgeom( env, var_name, var_value ) { static char xgeom[32]; - if (dsp_prop( DSP_GET, - DSP_XGEOM, - (void*)xgeom, - sizeof(xgeom) ) != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_XGEOM, (void*)xgeom, sizeof(xgeom) ) != DSP_SUCCEED) { *var_value = NULL; return False; @@ -716,16 +732,14 @@ int var_set_maxlen( env, var_name, var_value ) return False; } - maxlen = atoi(*var_value); + maxlen = (*var_value != NULL) ? atoi(*var_value) : 0; - if (dsp_prop( DSP_SET, DSP_MAXLEN, (void*)&maxlen, DSP_UNUSED ) - != DSP_SUCCEED) + if (dsp_prop( DSP_SET, DSP_MAXLEN, (void*)&maxlen, DSP_UNUSED ) != DSP_SUCCEED) { return False; } - DBG(sqsh_debug(DEBUG_SCREEN, - "var_set_maxlen: Maximum column width now set to %s\n", *var_value);) + DBG(sqsh_debug(DEBUG_SCREEN, "var_set_maxlen: Maximum column width now set to %s\n", *var_value);) return True ; } @@ -738,8 +752,7 @@ int var_get_maxlen( env, var_name, var_value ) static char nbr[16]; int maxlen; - if (dsp_prop( DSP_GET, DSP_MAXLEN, (void*)&maxlen, DSP_UNUSED) - != DSP_SUCCEED) + if (dsp_prop( DSP_GET, DSP_MAXLEN, (void*)&maxlen, DSP_UNUSED) != DSP_SUCCEED) { *var_value = NULL; return False; diff --git a/src/var_misc.c b/src/var_misc.c index 648e097..a0881fa 100644 --- a/src/var_misc.c +++ b/src/var_misc.c @@ -29,10 +29,13 @@ #include "sqsh_error.h" #include "sqsh_stdin.h" #include "var.h" +#include "sqsh_global.h" +#include "sqsh_fd.h" +#include "sqsh_expand.h" /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_misc.c,v 1.1.1.1 2004/04/07 12:35:05 chunkm0nkey Exp $" ; +static char RCS_Id[] = "$Id: var_misc.c,v 1.8 2014/03/12 14:40:43 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -113,7 +116,7 @@ int var_set_esc( env, var_name, var_value ) /* * Allow them to set the string to a null value. */ - if( *var_value == NULL || strcmp(*var_value,"NULL") == 0 ) { + if( var_value == NULL || *var_value == NULL || strcasecmp(*var_value,"NULL") == 0 ) { *var_value = NULL ; return True ; } @@ -124,7 +127,7 @@ int var_set_esc( env, var_name, var_value ) if( *src == '\\' ) { ++src ; switch( *src ) { - case 'n' : + case 'n' : *dst++ = '\n' ; break ; case 'f' : @@ -189,7 +192,7 @@ int var_set_notempty( env, var_name, var_value ) sqsh_set_error( SQSH_E_INVAL, "Invalid value" ) ; return False ; } - + return True ; } @@ -218,7 +221,7 @@ int var_set_bool( env, var_name, var_value ) return True ; /*-- Map True or Yes to 1 --*/ - if( strcasecmp( *var_value, "True" ) == 0 || + if( strcasecmp( *var_value, "True" ) == 0 || strcasecmp( *var_value, "Yes" ) == 0 || strcasecmp( *var_value, "On" ) == 0 ) { *var_value = "1" ; @@ -226,7 +229,7 @@ int var_set_bool( env, var_name, var_value ) } /*-- Map False or No to 0 --*/ - if( strcasecmp( *var_value, "False" ) == 0 || + if( strcasecmp( *var_value, "False" ) == 0 || strcasecmp( *var_value, "No" ) == 0 || strcasecmp( *var_value, "Off" ) == 0 ) { *var_value = "0" ; @@ -244,8 +247,10 @@ int var_set_nullint( env, var_name, var_value ) { char *cptr ; - if( *var_value == NULL || strcmp(*var_value, "NULL") == 0 ) - *var_value = "0" ; + if( var_value == NULL || *var_value == NULL || strcasecmp(*var_value, "NULL") == 0 ) { + *var_value = NULL ; + return True; + } /*-- Skip whitespace --*/ for( cptr = *var_value; *cptr != '\0' && isspace( (int)*cptr ); ++cptr ) ; @@ -269,7 +274,7 @@ int var_set_nullstr( env, var_name, var_value ) char *var_name ; char **var_value ; { - if( *var_value == NULL || strcmp( *var_value, "NULL" ) == 0 ) + if( var_value == NULL || *var_value == NULL || strcasecmp( *var_value, "NULL" ) == 0 ) *var_value = NULL ; return True ; @@ -286,7 +291,7 @@ int var_set_int( env, var_name, var_value ) char **var_value ; { /*-- Can't set it a NULL value --*/ - if( var_value == NULL || *var_value == NULL ) { + if( var_value == NULL || *var_value == NULL || strcasecmp(*var_value, "NULL") == 0) { sqsh_set_error( SQSH_E_INVAL, "Invalid integer expression" ) ; return False ; } @@ -330,7 +335,7 @@ int var_set_add( env, var_name, var_value ) if( !isdigit((int)*value) ) n = value + 1 ; - else + else n = value ; /*-- Check the digits --*/ @@ -411,3 +416,132 @@ int var_set_path_r( env, var_name, var_value ) return True; } + +/* + * var_set_lconv() - sqsh-2.3 + * + * Validation function for setting variable localeconv (1/0, True/False, Yes/No) + * When set to true, initialize variable g_lconv to localeconv(), NULL otherwise. + * Returns True if validation succeed, False otherwise. + */ +int var_set_lconv( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + /* + * Perform simple validations. + */ + if( var_value == NULL || *var_value == NULL || **var_value == '\0' ) { + sqsh_set_error( SQSH_E_INVAL, "Invalid boolean value" ) ; + return False ; + } + + /*-- Map True or Yes to 1 --*/ + if( strcasecmp( *var_value, "True" ) == 0 || + strcasecmp( *var_value, "Yes" ) == 0 || + strcasecmp( *var_value, "On" ) == 0 ) { + *var_value = "1" ; + } + /*-- Map False or No to 0 --*/ + else if( strcasecmp( *var_value, "False" ) == 0 || + strcasecmp( *var_value, "No" ) == 0 || + strcasecmp( *var_value, "Off" ) == 0 ) { + *var_value = "0" ; + } + + if( strcmp( *var_value, "1" ) == 0 ) + { +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) && defined(HAVE_LOCALECONV) + setlocale ( LC_ALL, "" ); + g_lconv = localeconv(); + return True; +#else + g_lconv = NULL; + *var_value = "0" ; + sqsh_set_error( SQSH_E_INVAL, "setlocale() and/or localeconv() not available" ) ; + return False; +#endif + } + else if( strcmp( *var_value, "0" ) == 0 ) + { +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) + setlocale ( LC_ALL, "C" ); +#endif + g_lconv = NULL; + return True; + } + + sqsh_set_error( SQSH_E_INVAL, "Invalid boolean value" ) ; + return False ; +} + +/* + * sqsh-2.5 - New feature p2f (Print to File) + * Assume var_name == "p2fname" + */ +int var_set_p2fname( env, var_name, var_value ) + env_t *env ; + char *var_name ; + char **var_value ; +{ + varbuf_t *exp_buf = NULL; + FILE *nfp = NULL; + char *exp_fn; + + + if ( var_name == NULL || strcmp(var_name, "p2fname") != 0 ) + { + sqsh_set_error( SQSH_E_INVAL, "var_set_p2fname: Unexpected variable name %s", var_name == NULL ? "NULL" : var_name ) ; + return False; + } + + if ( var_value == NULL || *var_value == NULL || strcasecmp( *var_value, "NULL" ) == 0 ) + { + *var_value = NULL ; + } + else { + if ((exp_buf = varbuf_create( 512 )) == NULL) + { + fprintf( stderr, "sqsh: %s\n", sqsh_get_errstr() ); + sqsh_set_error( SQSH_E_INVAL, "Unable to expand filename %s", *var_value ) ; + *var_value = NULL ; + return False; + } + + if (sqsh_expand( *var_value, exp_buf, 0 ) != False) + { + exp_fn = varbuf_getstr( exp_buf ); + } + else + { + sqsh_set_error( SQSH_E_INVAL, "Unable to expand filename %s", *var_value ) ; + *var_value = NULL ; + varbuf_destroy( exp_buf ); + return False; + } + + if( (nfp = fopen( exp_fn, "a" )) == NULL) + { + sqsh_set_error( SQSH_E_INVAL, "Unable to open file %s", exp_fn ) ; + *var_value = NULL ; + varbuf_destroy( exp_buf ); + return False; + } + varbuf_destroy( exp_buf ); + } + + /* + * If we come here, the fopen of the new file was successfull, or the p2fname variable is + * set to NULL. Either way, we can close the original file pointer if it is open + * and assign g_p2f_fp the new file pointer value (that still might be NULL). + */ + if (g_p2f_fp != NULL) + { + fclose (g_p2f_fp); + } + g_p2f_fp = nfp; + + return True ; +} + diff --git a/src/var_passwd.c b/src/var_passwd.c index 0f22819..2b1b781 100644 --- a/src/var_passwd.c +++ b/src/var_passwd.c @@ -31,7 +31,7 @@ /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_passwd.c,v 1.2 2005/04/05 16:17:42 mpeppler Exp $"; +static char RCS_Id[] = "$Id: var_passwd.c,v 1.3 2014/03/12 14:40:43 mwesdorp Exp $"; USE(RCS_Id) #endif /* !defined(lint) */ @@ -45,7 +45,7 @@ int var_set_lock( env, var_name, var_value ) /* * Allow them to set the string to a null value. */ - if ( *var_value == NULL || strcmp(*var_value,"NULL") == 0 ) { + if ( *var_value == NULL || strcasecmp(*var_value,"NULL") == 0 ) { /*-- Free up the old value --*/ if (g_lock != NULL) @@ -105,11 +105,11 @@ int var_set_password( env, var_name, var_value ) /* * Allow them to set the string to a null value. */ - if ( *var_value == NULL || strcmp(*var_value,"NULL") == 0 ) { + if ( *var_value == NULL || strcasecmp(*var_value,"NULL") == 0 ) { - /* Helmut Ruholl adds the strcmp() to handle password + /* Helmut Ruholl adds the strcasecmp() to handle password resets in .sqsh_session. mpeppler 2004-12-07 */ - if (*var_value != NULL && strcmp(*var_value, "NULL")) + if (*var_value != NULL && strcasecmp(*var_value, "NULL")) { g_password_set = False; } diff --git a/src/var_readline.c b/src/var_readline.c index ac5865e..e6e41d7 100644 --- a/src/var_readline.c +++ b/src/var_readline.c @@ -27,17 +27,12 @@ #include "sqsh_config.h" #include "sqsh_env.h" #include "sqsh_error.h" +#include "sqsh_readline.h" #include "var.h" -#if defined(USE_READLINE) -#include <readline/readline.h> -extern void stifle_history(); -extern void unstifle_history(); -#endif - /*-- Current Version --*/ #if !defined(lint) && !defined(__LINT__) -static char RCS_Id[] = "$Id: var_readline.c,v 1.1.1.1 2004/04/07 12:35:04 chunkm0nkey Exp $" ; +static char RCS_Id[] = "$Id: var_readline.c,v 1.3 2013/12/24 13:23:19 mwesdorp Exp $" ; USE(RCS_Id) #endif /* !defined(lint) */ @@ -53,7 +48,7 @@ int var_set_rl_histsize( env, var_name, var_value ) return False; } - stifle_value = atoi(*var_value); + stifle_value = (*var_value != NULL) ? atoi(*var_value) : 0; #if defined(USE_READLINE) if (stifle_value <= 0) |