📄 shell.c
字号:
int i, j; int nPrintCol, nPrintRow; for(i=1; i<=nRow; i++){ if( azResult[i]==0 ) continue; len = strlen(azResult[i]); if( len>maxlen ) maxlen = len; } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; i<nPrintRow; i++){ for(j=i+1; j<=nRow; j+=nPrintRow){ char *zSp = j<=nPrintRow ? "" : " "; printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); } printf("\n"); } } sqlite_free_table(azResult); }else if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ open_db(p); sqlite_busy_timeout(p->db, atoi(azArg[1])); }else if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ int j; for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } }else { fprintf(stderr, "unknown command or invalid arguments: " " \"%s\". Enter \".help\" for help\n", azArg[0]); } return rc;}/*** Return TRUE if the last non-whitespace character in z[] is a semicolon.** z[] is N characters long.*/static int _ends_with_semicolon(const char *z, int N){ while( N>0 && isspace(z[N-1]) ){ N--; } return N>0 && z[N-1]==';';}/*** Test to see if a line consists entirely of whitespace.*/static int _all_whitespace(const char *z){ for(; *z; z++){ if( isspace(*z) ) continue; if( *z=='/' && z[1]=='*' ){ z += 2; while( *z && (*z!='*' || z[1]!='/') ){ z++; } if( *z==0 ) return 0; z++; continue; } if( *z=='-' && z[1]=='-' ){ z += 2; while( *z && *z!='\n' ){ z++; } if( *z==0 ) return 1; continue; } return 0; } return 1;}/*** Return TRUE if the line typed in is an SQL command terminator other** than a semi-colon. The SQL Server style "go" command is understood** as is the Oracle "/".*/static int _is_command_terminator(const char *zLine){ extern int sqliteStrNICmp(const char*,const char*,int); while( isspace(*zLine) ){ zLine++; }; if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ) return 1; /* Oracle */ if( sqliteStrNICmp(zLine,"go",2)==0 && _all_whitespace(&zLine[2]) ){ return 1; /* SQL Server */ } return 0;}/*** Read input from *in and process it. If *in==0 then input** is interactive - the user is typing it it. Otherwise, input** is coming from a file or device. A prompt is issued and history** is saved only if input is interactive. An interrupt signal will** cause this routine to exit immediately, unless input is interactive.*/static void process_input(struct callback_data *p, FILE *in){ char *zLine; char *zSql = 0; int nSql = 0; char *zErrMsg; int rc; while( fflush(p->out), (zLine = one_input_line(zSql, in))!=0 ){ if( seenInterrupt ){ if( in!=0 ) break; seenInterrupt = 0; } if( p->echoOn ) printf("%s\n", zLine); if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; if( zLine && zLine[0]=='.' && nSql==0 ){ int rc = do_meta_command(zLine, p); free(zLine); if( rc ) break; continue; } if( _is_command_terminator(zLine) ){ strcpy(zLine,";"); } if( zSql==0 ){ int i; for(i=0; zLine[i] && isspace(zLine[i]); i++){} if( zLine[i]!=0 ){ nSql = strlen(zLine); zSql = malloc( nSql+1 ); strcpy(zSql, zLine); } }else{ int len = strlen(zLine); zSql = realloc( zSql, nSql + len + 2 ); if( zSql==0 ){ fprintf(stderr,"%s: out of memory!\n", Argv0); exit(1); } strcpy(&zSql[nSql++], "\n"); strcpy(&zSql[nSql], zLine); nSql += len; } free(zLine); if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite_complete(zSql) ){ p->cnt = 0; open_db(p); rc = sqlite_exec(p->db, zSql, callback, p, &zErrMsg); if( rc || zErrMsg ){ if( in!=0 && !p->echoOn ) printf("%s\n",zSql); if( zErrMsg!=0 ){ printf("SQL error: %s\n", zErrMsg); free(zErrMsg); zErrMsg = 0; }else{ printf("SQL error: %s\n", sqlite_error_string(rc)); } } free(zSql); zSql = 0; nSql = 0; } } if( zSql ){ if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql); free(zSql); }}/*** Return a pathname which is the user's home directory. A** 0 return indicates an error of some kind. Space to hold the** resulting string is obtained from malloc(). The calling** function should free the result.*/static char *find_home_dir(void){ char *home_dir = NULL;#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { home_dir = pwent->pw_dir; }#endif#ifdef __MACOS__ char home_path[_MAX_PATH+1]; home_dir = getcwd(home_path, _MAX_PATH);#endif if (!home_dir) { home_dir = getenv("HOME"); if (!home_dir) { home_dir = getenv("HOMEPATH"); /* Windows? */ } }#if defined(_WIN32) || defined(WIN32) if (!home_dir) { home_dir = "c:"; }#endif if( home_dir ){ char *z = malloc( strlen(home_dir)+1 ); if( z ) strcpy(z, home_dir); home_dir = z; } return home_dir;}/*** Read input from the file given by sqliterc_override. Or if that** parameter is NULL, take input from ~/.sqliterc*/static void process_sqliterc(struct callback_data *p, char *sqliterc_override){ char *home_dir = NULL; char *sqliterc = sqliterc_override; FILE *in = NULL; if (sqliterc == NULL) { home_dir = find_home_dir(); if( home_dir==0 ){ fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0); return; } sqliterc = malloc(strlen(home_dir) + 15); if( sqliterc==0 ){ fprintf(stderr,"%s: out of memory!\n", Argv0); exit(1); } sprintf(sqliterc,"%s/.sqliterc",home_dir); free(home_dir); } in = fopen(sqliterc,"r"); if(in && isatty(fileno(stdout))) { printf("Loading resources from %s\n",sqliterc); process_input(p,in); fclose(in); } return;}/*** Show available command line options*/static const char zOptions[] = " -init filename read/process named file\n" " -echo print commands before execution\n" " -[no]header turn headers on or off\n" " -column set output mode to 'column'\n" " -html set output mode to HTML\n" " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" " -separator 'x' set output field separator (|)\n" " -nullvalue 'text' set text string for NULL values\n" " -version show SQLite version\n" " -help show this text, also show dot-commands\n";static void usage(int showDetail){ fprintf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n", Argv0); if( showDetail ){ fprintf(stderr, "Options are:\n%s", zOptions); }else{ fprintf(stderr, "Use the -help option for additional information\n"); } exit(1);}/*** Initialize the state information in data*/void main_init(struct callback_data *data) { memset(data, 0, sizeof(*data)); data->mode = MODE_List; strcpy(data->separator,"|"); data->showHeader = 0; strcpy(mainPrompt,"sqlite> "); strcpy(continuePrompt," ...> ");}int main(int argc, char **argv){ char *zErrMsg = 0; struct callback_data data; int origArgc = argc; char **origArgv = argv; int i; extern int sqliteOsFileExists(const char*);#ifdef __MACOS__ argc = ccommand(&argv); origArgc = argc; origArgv = argv;#endif Argv0 = argv[0]; main_init(&data); /* Make sure we have a valid signal handler early, before anything ** else is done. */#ifdef SIGINT signal(SIGINT, interrupt_handler);#endif /* Locate the name of the database file */ for(i=1; i<argc; i++){ if( argv[i][0]!='-' ) break; if( strcmp(argv[i],"-separator")==0 || strcmp(argv[i],"-nullvalue")==0 ){ i++; } } data.zDbFilename = i<argc ? argv[i] : ":memory:"; data.out = stdout; /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database ** files from being created if a user mistypes the database name argument ** to the sqlite command-line tool. */ if( sqliteOsFileExists(data.zDbFilename) ){ open_db(&data); } /* Process the ~/.sqliterc file, if there is one */ process_sqliterc(&data,NULL); /* Process command-line options */ while( argc>=2 && argv[1][0]=='-' ){ if( argc>=3 && strcmp(argv[1],"-init")==0 ){ /* If we get a -init to do, we have to pretend that ** it replaced the .sqliterc file. Soooo, in order to ** do that we need to start from scratch...*/ main_init(&data); /* treat this file as the sqliterc... */ process_sqliterc(&data,argv[2]); /* fix up the command line so we do not re-read ** the option next time around... */ { int i = 1; for(i=1;i<=argc-2;i++) { argv[i] = argv[i+2]; } } origArgc-=2; /* and reset the command line options to be re-read.*/ argv = origArgv; argc = origArgc; }else if( strcmp(argv[1],"-html")==0 ){ data.mode = MODE_Html; argc--; argv++; }else if( strcmp(argv[1],"-list")==0 ){ data.mode = MODE_List; argc--; argv++; }else if( strcmp(argv[1],"-line")==0 ){ data.mode = MODE_Line; argc--; argv++; }else if( strcmp(argv[1],"-column")==0 ){ data.mode = MODE_Column; argc--; argv++; }else if( argc>=3 && strcmp(argv[1],"-separator")==0 ){ sprintf(data.separator,"%.*s",(int)sizeof(data.separator)-1,argv[2]); argc -= 2; argv += 2; }else if( argc>=3 && strcmp(argv[1],"-nullvalue")==0 ){ sprintf(data.nullvalue,"%.*s",(int)sizeof(data.nullvalue)-1,argv[2]); argc -= 2; argv += 2; }else if( strcmp(argv[1],"-header")==0 ){ data.showHeader = 1; argc--; argv++; }else if( strcmp(argv[1],"-noheader")==0 ){ data.showHeader = 0; argc--; argv++; }else if( strcmp(argv[1],"-echo")==0 ){ data.echoOn = 1; argc--; argv++; }else if( strcmp(argv[1],"-version")==0 ){ printf("%s\n", sqlite_version); return 1; }else if( strcmp(argv[1],"-help")==0 ){ usage(1); }else{ fprintf(stderr,"%s: unknown option: %s\n", Argv0, argv[1]); fprintf(stderr,"Use -help for a list of options.\n"); return 1; } } if( argc<2 ){ usage(0); }else if( argc==3 ){ /* Run just the command that follows the database name */ if( argv[2][0]=='.' ){ do_meta_command(argv[2], &data); exit(0); }else{ int rc; open_db(&data); rc = sqlite_exec(db, argv[2], callback, &data, &zErrMsg); if( rc!=0 && zErrMsg!=0 ){ fprintf(stderr,"SQL error: %s\n", zErrMsg); exit(1); } } }else{ /* Run commands received from standard input */ if( isatty(fileno(stdout)) && isatty(fileno(stdin)) ){ char *zHome; char *zHistory = 0; printf( "SQLite version %s\n" "Enter \".help\" for instructions\n", sqlite_version ); zHome = find_home_dir(); if( zHome && (zHistory = malloc(strlen(zHome)+20))!=0 ){ sprintf(zHistory,"%s/.sqlite_history", zHome); } if( zHistory ) read_history(zHistory); process_input(&data, 0); if( zHistory ){ stifle_history(100); write_history(zHistory); } }else{ process_input(&data, stdin); } } set_table_name(&data, 0); if( db ) sqlite_close(db); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -