/ Check-in [ca4abf3f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for saving the sqlite shell command-line history across sessions. (CVS 536)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ca4abf3fe1f0e66802f9f98a20e0c8b82a6459aa
User & Date: drh 2002-04-19 12:34:06
Context
2002-04-20
14:24
Fix for ticket #1: Implement the GLOB and LIKE operators as functions that can be overridden. This way, a developer can change the LIKE operator to be case sensitive, for example. (CVS 537) check-in: 51572bf7 user: drh tags: trunk
2002-04-19
12:34
Add support for saving the sqlite shell command-line history across sessions. (CVS 536) check-in: ca4abf3f user: drh tags: trunk
01:00
Added rights release for Matthew O. Persico (CVS 535) check-in: 6c32c07e user: persicom tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

     4      4   ** The author disclaims copyright to this source code.  In place of
     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11         -** 2002 April 18
    12         -**
    13         -** I, Matthew O. Persico, hereby release all edits made by me to
    14         -** this source into the public domain.
    15     11   *************************************************************************
    16     12   ** This file contains code to implement the "sqlite" command line
    17     13   ** utility for accessing SQLite databases.
    18     14   **
    19         -** $Id: shell.c,v 1.54 2002/04/19 01:00:13 persicom Exp $
           15  +** $Id: shell.c,v 1.55 2002/04/19 12:34:06 drh Exp $
    20     16   */
    21     17   #include <stdlib.h>
    22     18   #include <string.h>
    23     19   #include <stdio.h>
    24     20   #include "sqlite.h"
    25     21   #include <ctype.h>
    26     22   
................................................................................
    33     29   
    34     30   #if defined(HAVE_READLINE) && HAVE_READLINE==1
    35     31   # include <readline/readline.h>
    36     32   # include <readline/history.h>
    37     33   #else
    38     34   # define readline(p) getline(p,stdin)
    39     35   # define add_history(X)
           36  +# define read_history(X)
           37  +# define write_history(X)
           38  +# define stifle_history(X)
    40     39   #endif
    41     40   
    42     41   /*
    43     42   ** The following is the open SQLite database.  We make a pointer
    44     43   ** to this database a static variable so that it can be accessed
    45     44   ** by the SIGINT handler to interrupt database processing.
    46     45   */
    47     46   static sqlite *db = 0;
    48     47   
           48  +/*
           49  +** True if an interrupt (Control-C) has been received.
           50  +*/
           51  +static int seenInterrupt = 0;
           52  +
    49     53   /*
    50     54   ** This is the name of our program. It is set in main(), used
    51     55   ** in a number of other places, mostly for error messages.
    52     56   */
    53     57   static char *Argv0;
    54     58   
    55     59   /*
................................................................................
   269    273     }
   270    274   }
   271    275   
   272    276   /*
   273    277   ** This routine runs when the user presses Ctrl-C
   274    278   */
   275    279   static void interrupt_handler(int NotUsed){
          280  +  seenInterrupt = 1;
   276    281     if( db ) sqlite_interrupt(db);
   277    282   }
   278    283   
   279    284   /*
   280    285   ** This is the callback routine that the SQLite library
   281    286   ** invokes for each row of a query result.
   282    287   */
................................................................................
   502    507   
   503    508   /* Forward reference */
   504    509   static void process_input(struct callback_data *p, FILE *in);
   505    510   
   506    511   /*
   507    512   ** If an input line begins with "." then invoke this routine to
   508    513   ** process that line.
          514  +**
          515  +** Return 1 to exit and 0 to continue.
   509    516   */
   510         -static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
          517  +static int do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
   511    518     int i = 1;
   512    519     int nArg = 0;
   513    520     int n, c;
          521  +  int rc = 0;
   514    522     char *azArg[50];
   515    523   
   516    524     /* Parse the input line into tokens.
   517    525     */
   518    526     while( zLine[i] && nArg<ArraySize(azArg) ){
   519    527       while( isspace(zLine[i]) ){ i++; }
   520    528       if( zLine[i]=='\'' || zLine[i]=='"' ){
................................................................................
   529    537         while( zLine[i] && !isspace(zLine[i]) ){ i++; }
   530    538         if( zLine[i] ) zLine[i++] = 0;
   531    539       }
   532    540     }
   533    541   
   534    542     /* Process the input line.
   535    543     */
   536         -  if( nArg==0 ) return;
          544  +  if( nArg==0 ) return rc;
   537    545     n = strlen(azArg[0]);
   538    546     c = azArg[0][0];
   539    547     if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
   540    548       char *zErrMsg = 0;
   541    549       fprintf(p->out, "BEGIN TRANSACTION;\n");
   542    550       if( nArg==1 ){
   543    551         sqlite_exec(db,
................................................................................
   577    585       }else if( strcmp(z,"yes")==0 ){
   578    586         val = 1;
   579    587       }
   580    588       p->echoOn = val;
   581    589     }else
   582    590   
   583    591     if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
   584         -    sqlite_close(db);
   585         -    exit(0);
          592  +    rc = 1;
   586    593     }else
   587    594   
   588    595     if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
   589    596       int j;
   590    597       char *z = nArg>=2 ? azArg[1] : "1";
   591    598       int val = atoi(z);
   592    599       for(j=0; z[j]; j++){
................................................................................
   817    824     if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){
   818    825       sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]);
   819    826     }else
   820    827   
   821    828     if( c=='s' && strncmp(azArg[0], "show", n)==0){
   822    829       int i;
   823    830       fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
   824         -    fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" : "off");
          831  +    fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
   825    832       fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
   826    833       fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
   827    834       fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue);
   828         -    fprintf(p->out,"%9.9s: %s\n","output", strlen(p->outfile) ? p->outfile : "stdout");
          835  +    fprintf(p->out,"%9.9s: %s\n","output",
          836  +                                 strlen(p->outfile) ? p->outfile : "stdout");
   829    837       fprintf(p->out,"%9.9s: %s\n","separator", p->separator);
   830    838       fprintf(p->out,"%9.9s: ","width");
   831    839       for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
   832    840           fprintf(p->out,"%d ",p->colWidth[i]);
   833    841       }
   834    842       fprintf(p->out,"\n\n");
   835    843     }else
................................................................................
   888    896       int j;
   889    897       for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
   890    898         p->colWidth[j-1] = atoi(azArg[j]);
   891    899       }
   892    900     }else
   893    901   
   894    902     {
   895         -    fprintf(stderr, "unknown command or invalid arguments: \"%s\". Enter \".help\" for help\n",
   896         -      azArg[0]);
          903  +    fprintf(stderr, "unknown command or invalid arguments: "
          904  +      " \"%s\". Enter \".help\" for help\n", azArg[0]);
   897    905     }
          906  +
          907  +  return rc;
   898    908   }
   899    909   
          910  +/*
          911  +** Read input from *in and process it.  If *in==0 then input
          912  +** is interactive - the user is typing it it.  Otherwise, input
          913  +** is coming from a file or device.  A prompt is issued and history
          914  +** is saved only if input is interactive.  An interrupt signal will
          915  +** cause this routine to exit immediately, unless input is interactive.
          916  +*/
   900    917   static void process_input(struct callback_data *p, FILE *in){
   901    918     char *zLine;
   902    919     char *zSql = 0;
   903    920     int nSql = 0;
   904    921     char *zErrMsg;
   905    922     while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){
          923  +    if( seenInterrupt ){
          924  +      if( in!=0 ) break;
          925  +      seenInterrupt = 0;
          926  +    }
   906    927       if( p->echoOn ) printf("%s\n", zLine);
   907    928       if( zLine && zLine[0]=='.' && nSql==0 ){
   908         -      do_meta_command(zLine, db, p);
          929  +      int rc = do_meta_command(zLine, db, p);
   909    930         free(zLine);
          931  +      if( rc ) break;
   910    932         continue;
   911    933       }
   912    934       if( zSql==0 ){
   913    935         int i;
   914    936         for(i=0; zLine[i] && isspace(zLine[i]); i++){}
   915    937         if( zLine[i]!=0 ){
   916    938           nSql = strlen(zLine);
................................................................................
   945    967     }
   946    968     if( zSql ){
   947    969       printf("Incomplete SQL: %s\n", zSql);
   948    970       free(zSql);
   949    971     }
   950    972   }
   951    973   
   952         -static void process_sqliterc(struct callback_data *p,
   953         -                             char *sqliterc_override){
          974  +/*
          975  +** Return a pathname which is the user's home directory.  A
          976  +** 0 return indicates an error of some kind.  Space to hold the
          977  +** resulting string is obtained from malloc().  The calling
          978  +** function should free the result.
          979  +*/
          980  +static char *find_home_dir(void){
          981  +  char *home_dir = NULL;
          982  +
          983  +#if !defined(_WIN32) && !defined(WIN32)
          984  +  struct passwd *pwent;
          985  +  uid_t uid = getuid();
          986  +  while( (pwent=getpwent()) != NULL) {
          987  +    if(pwent->pw_uid == uid) {
          988  +      home_dir = pwent->pw_dir;
          989  +      break;
          990  +    }
          991  +  }
          992  +#endif
          993  +
          994  +  if (!home_dir) {
          995  +    home_dir = getenv("HOME");
          996  +    if (!home_dir) {
          997  +      home_dir = getenv("HOMEPATH"); /* Windows? */
          998  +    }
          999  +  }
         1000  +
         1001  +  if( home_dir ){
         1002  +    char *z = malloc( strlen(home_dir)+1 );
         1003  +    if( z ) strcpy(z, home_dir);
         1004  +    home_dir = z;
         1005  +  }
         1006  +  return home_dir;
         1007  +}
   954   1008   
         1009  +/*
         1010  +** Read input from the file given by sqliterc_override.  Or if that
         1011  +** parameter is NULL, take input from ~/.sqliterc
         1012  +*/
         1013  +static void process_sqliterc(struct callback_data *p, char *sqliterc_override){
   955   1014     char *home_dir = NULL;
   956   1015     char *sqliterc = sqliterc_override;
   957   1016     FILE *in = NULL;
   958   1017   
   959   1018     if (sqliterc == NULL) {
   960         -    /* Figure out the user's home directory */
   961         -#if !defined(_WIN32) && !defined(WIN32)
   962         -    struct passwd *pwent;
   963         -    uid_t uid = getuid();
   964         -    while( (pwent=getpwent()) != NULL) {
   965         -      if(pwent->pw_uid == uid) {
   966         -        home_dir = pwent->pw_dir;
   967         -        break;
   968         -      }
   969         -    }
   970         -#endif
   971         -
   972         -    if (!home_dir) {
   973         -      home_dir = getenv("HOME");
   974         -      if (!home_dir) {
   975         -        home_dir = getenv("HOMEPATH"); /* Windows? */
   976         -      }
   977         -      if (!home_dir) {
   978         -        printf("Cannot find home directory from which to load .sqliterc\n");
   979         -        return;
   980         -      }
   981         -    }
   982         -
   983         -    /* With the home directory, open the init file and process */
   984         -    sqliterc = (char *)calloc(strlen(home_dir) +
   985         -                              strlen("/.sqliterc") +
   986         -                              1,
   987         -                              sizeof(char));
         1019  +    home_dir = find_home_dir();
         1020  +    sqliterc = home_dir ? malloc(strlen(home_dir) + 15) : 0;
   988   1021       if( sqliterc==0 ){
   989   1022         fprintf(stderr,"%s: out of memory!\n", Argv0);
   990   1023         exit(1);
   991   1024       }
   992   1025       sprintf(sqliterc,"%s/.sqliterc",home_dir);
         1026  +    free(home_dir);
   993   1027     }
   994   1028     in = fopen(sqliterc,"r");
   995         -  if(!in) {
   996         -    /* File either had an error or was not found. Since I cannot
   997         -     * tell, I cannot bark. */
   998         -    return;
   999         -  } else {
         1029  +  if(in) {
  1000   1030       printf("Loading resources from %s\n",sqliterc);
  1001   1031       process_input(p,in);
  1002   1032       fclose(in);
  1003   1033     }
  1004   1034     return;
  1005   1035   }
  1006   1036   
         1037  +/*
         1038  +** Initialize the state information in data
         1039  +*/
  1007   1040   void main_init(struct callback_data *data) {
  1008   1041     memset(data, 0, sizeof(*data));
  1009   1042     data->mode = MODE_List;
  1010   1043     strcpy(data->separator,"|");
  1011   1044     data->showHeader = 0;
  1012   1045     strcpy(mainPrompt,"sqlite> ");
  1013   1046     strcpy(continuePrompt,"   ...> ");
................................................................................
  1121   1154           fprintf(stderr,"SQL error: %s\n", zErrMsg);
  1122   1155           exit(1);
  1123   1156         }
  1124   1157       }
  1125   1158     }else{
  1126   1159       extern int isatty();
  1127   1160       if( isatty(0) ){
         1161  +      char *zHome;
         1162  +      char *zHistory = 0;
  1128   1163         printf(
  1129   1164           "SQLite version %s\n"
  1130   1165           "Enter \".help\" for instructions\n",
  1131   1166           sqlite_version
  1132   1167         );
         1168  +      zHome = find_home_dir();
         1169  +      if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){
         1170  +        sprintf(zHistory,"%s/.sqlite_history", zHome);
         1171  +      }
         1172  +      if( zHistory ) read_history(zHistory);
  1133   1173         process_input(&data, 0);
         1174  +      if( zHistory ){
         1175  +        stifle_history(100);
         1176  +        write_history(zHistory);
         1177  +      }
  1134   1178       }else{
  1135   1179         process_input(&data, stdin);
  1136   1180       }
  1137   1181     }
  1138   1182     set_table_name(&data, 0);
  1139   1183     sqlite_close(db);
  1140   1184     return 0;
  1141   1185   }