33 *
44 * Copyright 2000 by PostgreSQL Global Development Group
55 *
6- * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.58 2001/09/10 14:51:33 momjian Exp $
6+ * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.59 2001/10/05 19:01:13 momjian Exp $
77 */
88#include "postgres_fe.h"
99#include "command.h"
@@ -58,7 +58,7 @@ enum option_type
5858{
5959OT_NORMAL ,OT_SQLID ,OT_FILEPIPE
6060};
61- static char * scan_option (char * * string ,enum option_type type ,char * quote );
61+ static char * scan_option (char * * string ,enum option_type type ,char * quote , bool semicolon );
6262static char * unescape (const unsignedchar * source ,size_t len );
6363
6464static bool do_edit (const char * filename_arg ,PQExpBuffer query_buf );
@@ -219,7 +219,7 @@ exec_command(const char *cmd,
219219/* \C -- override table title (formerly change HTML caption) */
220220else if (strcmp (cmd ,"C" )== 0 )
221221{
222- char * opt = scan_option (& string ,OT_NORMAL ,NULL );
222+ char * opt = scan_option (& string ,OT_NORMAL ,NULL , true );
223223
224224success = do_pset ("title" ,opt ,& pset .popt ,quiet );
225225free (opt );
@@ -241,8 +241,8 @@ exec_command(const char *cmd,
241241char opt1q ,
242242opt2q ;
243243
244- opt1 = scan_option (& string ,OT_SQLID ,& opt1q );
245- opt2 = scan_option (& string ,OT_SQLID ,& opt2q );
244+ opt1 = scan_option (& string ,OT_SQLID ,& opt1q , true );
245+ opt2 = scan_option (& string ,OT_SQLID ,& opt2q , true );
246246
247247if (opt2 )
248248/* gave username */
@@ -262,7 +262,7 @@ exec_command(const char *cmd,
262262/* \cd */
263263else if (strcmp (cmd ,"cd" )== 0 )
264264{
265- char * opt = scan_option (& string ,OT_NORMAL ,NULL );
265+ char * opt = scan_option (& string ,OT_NORMAL ,NULL , true );
266266char * dir ;
267267
268268if (opt )
@@ -315,8 +315,8 @@ exec_command(const char *cmd,
315315{
316316char * name ;
317317bool show_verbose ;
318+ name = scan_option (& string ,OT_SQLID ,NULL , true);
318319
319- name = scan_option (& string ,OT_SQLID ,NULL );
320320show_verbose = strchr (cmd ,'+' ) ? true : false;
321321
322322switch (cmd [1 ])
@@ -382,7 +382,7 @@ exec_command(const char *cmd,
382382}
383383else
384384{
385- fname = scan_option (& string ,OT_NORMAL ,NULL );
385+ fname = scan_option (& string ,OT_NORMAL ,NULL , true );
386386status = do_edit (fname ,query_buf ) ?CMD_NEWEDIT :CMD_ERROR ;
387387free (fname );
388388}
@@ -401,8 +401,8 @@ exec_command(const char *cmd,
401401fout = pset .queryFout ;
402402else
403403fout = stdout ;
404-
405- while ((value = scan_option (& string ,OT_NORMAL ,& quoted )))
404+
405+ while ((value = scan_option (& string ,OT_NORMAL ,& quoted , false )))
406406{
407407if (!quoted && strcmp (value ,"-n" )== 0 )
408408no_newline = true;
@@ -423,7 +423,7 @@ exec_command(const char *cmd,
423423/* \encoding -- set/show client side encoding */
424424else if (strcmp (cmd ,"encoding" )== 0 )
425425{
426- char * encoding = scan_option (& string ,OT_NORMAL ,NULL );
426+ char * encoding = scan_option (& string ,OT_NORMAL ,NULL , false );
427427
428428if (!encoding )
429429/* show encoding */
@@ -451,7 +451,7 @@ exec_command(const char *cmd,
451451/* \f -- change field separator */
452452else if (strcmp (cmd ,"f" )== 0 )
453453{
454- char * fname = scan_option (& string ,OT_NORMAL ,NULL );
454+ char * fname = scan_option (& string ,OT_NORMAL ,NULL , false );
455455
456456success = do_pset ("fieldsep" ,fname ,& pset .popt ,quiet );
457457free (fname );
@@ -460,7 +460,7 @@ exec_command(const char *cmd,
460460/* \g means send query */
461461else if (strcmp (cmd ,"g" )== 0 )
462462{
463- char * fname = scan_option (& string ,OT_FILEPIPE ,NULL );
463+ char * fname = scan_option (& string ,OT_FILEPIPE ,NULL , false );
464464
465465if (!fname )
466466pset .gfname = NULL ;
@@ -492,7 +492,7 @@ exec_command(const char *cmd,
492492/* \i is include file */
493493else if (strcmp (cmd ,"i" )== 0 || strcmp (cmd ,"include" )== 0 )
494494{
495- char * fname = scan_option (& string ,OT_NORMAL ,NULL );
495+ char * fname = scan_option (& string ,OT_NORMAL ,NULL , true );
496496
497497if (!fname )
498498{
@@ -520,8 +520,8 @@ exec_command(const char *cmd,
520520char * opt1 ,
521521* opt2 ;
522522
523- opt1 = scan_option (& string ,OT_NORMAL ,NULL );
524- opt2 = scan_option (& string ,OT_NORMAL ,NULL );
523+ opt1 = scan_option (& string ,OT_NORMAL ,NULL , true );
524+ opt2 = scan_option (& string ,OT_NORMAL ,NULL , true );
525525
526526if (strcmp (cmd + 3 ,"export" )== 0 )
527527{
@@ -570,7 +570,7 @@ exec_command(const char *cmd,
570570/* \o -- set query output */
571571else if (strcmp (cmd ,"o" )== 0 || strcmp (cmd ,"out" )== 0 )
572572{
573- char * fname = scan_option (& string ,OT_FILEPIPE ,NULL );
573+ char * fname = scan_option (& string ,OT_FILEPIPE ,NULL , true );
574574
575575success = setQFout (fname );
576576free (fname );
@@ -589,8 +589,8 @@ exec_command(const char *cmd,
589589/* \pset -- set printing parameters */
590590else if (strcmp (cmd ,"pset" )== 0 )
591591{
592- char * opt0 = scan_option (& string ,OT_NORMAL ,NULL );
593- char * opt1 = scan_option (& string ,OT_NORMAL ,NULL );
592+ char * opt0 = scan_option (& string ,OT_NORMAL ,NULL , false );
593+ char * opt1 = scan_option (& string ,OT_NORMAL ,NULL , false );
594594
595595if (!opt0 )
596596{
@@ -619,7 +619,7 @@ exec_command(const char *cmd,
619619/* \s save history in a file or show it on the screen */
620620else if (strcmp (cmd ,"s" )== 0 )
621621{
622- char * fname = scan_option (& string ,OT_NORMAL ,NULL );
622+ char * fname = scan_option (& string ,OT_NORMAL ,NULL , true );
623623
624624success = saveHistory (fname ?fname :"/dev/tty" );
625625
@@ -631,7 +631,7 @@ exec_command(const char *cmd,
631631/* \set -- generalized set variable/option command */
632632else if (strcmp (cmd ,"set" )== 0 )
633633{
634- char * opt0 = scan_option (& string ,OT_NORMAL ,NULL );
634+ char * opt0 = scan_option (& string ,OT_NORMAL ,NULL , false );
635635
636636if (!opt0 )
637637{
@@ -656,11 +656,11 @@ exec_command(const char *cmd,
656656char * newval = NULL ;
657657char * opt ;
658658
659- opt = scan_option (& string ,OT_NORMAL ,NULL );
659+ opt = scan_option (& string ,OT_NORMAL ,NULL , false );
660660newval = xstrdup (opt ?opt :"" );
661661free (opt );
662662
663- while ((opt = scan_option (& string ,OT_NORMAL ,NULL )))
663+ while ((opt = scan_option (& string ,OT_NORMAL ,NULL , false )))
664664{
665665newval = realloc (newval ,strlen (newval )+ strlen (opt )+ 1 );
666666if (!newval )
@@ -690,7 +690,7 @@ exec_command(const char *cmd,
690690/* \T -- define html <table ...> attributes */
691691else if (strcmp (cmd ,"T" )== 0 )
692692{
693- char * value = scan_option (& string ,OT_NORMAL ,NULL );
693+ char * value = scan_option (& string ,OT_NORMAL ,NULL , false );
694694
695695success = do_pset ("tableattr" ,value ,& pset .popt ,quiet );
696696free (value );
@@ -699,7 +699,7 @@ exec_command(const char *cmd,
699699/* \unset */
700700else if (strcmp (cmd ,"unset" )== 0 )
701701{
702- char * opt = scan_option (& string ,OT_NORMAL ,NULL );
702+ char * opt = scan_option (& string ,OT_NORMAL ,NULL , false );
703703
704704if (!opt )
705705{
@@ -728,7 +728,7 @@ exec_command(const char *cmd,
728728}
729729else
730730{
731- fname = scan_option (& string ,OT_FILEPIPE ,NULL );
731+ fname = scan_option (& string ,OT_FILEPIPE ,NULL , true );
732732
733733if (!fname )
734734{
@@ -783,7 +783,7 @@ exec_command(const char *cmd,
783783/* \z -- list table rights (grant/revoke) */
784784else if (strcmp (cmd ,"z" )== 0 )
785785{
786- char * opt = scan_option (& string ,OT_SQLID ,NULL );
786+ char * opt = scan_option (& string ,OT_SQLID ,NULL , true );
787787
788788success = permissionsList (opt );
789789free (opt );
@@ -814,7 +814,7 @@ exec_command(const char *cmd,
814814char * value ;
815815
816816fprintf (stderr ,"+ optstr = |%s|\n" ,options_string );
817- while ((value = scan_option (& string ,OT_NORMAL ,NULL )))
817+ while ((value = scan_option (& string ,OT_NORMAL ,NULL , true )))
818818{
819819fprintf (stderr ,"+ opt(%d) = |%s|\n" ,i ++ ,value );
820820free (value );
@@ -829,7 +829,7 @@ exec_command(const char *cmd,
829829status = CMD_ERROR ;
830830
831831/* eat the rest of the options string */
832- while ((val = scan_option (& string ,OT_NORMAL ,NULL )))
832+ while ((val = scan_option (& string ,OT_NORMAL ,NULL , false )))
833833{
834834if (status != CMD_UNKNOWN )
835835psql_error ("\\%s: extra argument '%s' ignored\n" ,cmd ,val );
@@ -848,7 +848,7 @@ exec_command(const char *cmd,
848848 * scan_option()
849849 */
850850static char *
851- scan_option (char * * string ,enum option_type type ,char * quote )
851+ scan_option (char * * string ,enum option_type type ,char * quote , bool semicolon )
852852{
853853unsignedint pos = 0 ;
854854char * options_string ;
@@ -905,6 +905,7 @@ scan_option(char **string, enum option_type type, char *quote)
905905 * If this is expected to be an SQL identifier like option
906906 * then we strip out the double quotes
907907 */
908+
908909if (type == OT_SQLID )
909910{
910911unsignedint k ,
@@ -936,7 +937,7 @@ scan_option(char **string, enum option_type type, char *quote)
936937* string = options_string + jj + 1 ;
937938if (quote )
938939* quote = '"' ;
939-
940+
940941return return_val ;
941942}
942943
@@ -1117,6 +1118,13 @@ scan_option(char **string, enum option_type type, char *quote)
11171118strncpy (return_val ,& options_string [pos ],token_end );
11181119return_val [token_end ]= 0 ;
11191120
1121+ /* Strip any trailing semi-colons for some types */
1122+ if (semicolon ) {
1123+ int i ;
1124+ for (i = strlen (return_val )- 1 ;i && return_val [i ]== ';' ;i -- );
1125+ if (i < strlen (return_val )- 1 )return_val [i + 1 ]= '\0' ;
1126+ }
1127+
11201128if (type == OT_SQLID )
11211129for (cp = return_val ;* cp ;cp += PQmblen (cp ,pset .encoding ))
11221130if (isupper ((unsignedchar )* cp ))