diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
| commit | 4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch) | |
| tree | c296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /src/fshell.c | |
| download | relic-master.tar.gz | |
Diffstat (limited to 'src/fshell.c')
| -rw-r--r-- | src/fshell.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/fshell.c b/src/fshell.c new file mode 100644 index 0000000..977e124 --- /dev/null +++ b/src/fshell.c @@ -0,0 +1,130 @@ +/* +** Copyright (c) 2016 D. Richard Hipp +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the Simplified BSD License (also +** known as the "2-Clause License" or "FreeBSD License".) + +** 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. +** +** Author contact information: +** drh@hwaci.com +** http://www.hwaci.com/drh/ +** +******************************************************************************* +** +** This module contains the code that implements the "fossil shell" command. +** +** The fossil shell prompts for lines of user input, then parses each line +** after the fashion of a standard Bourne shell and forks a child process +** to run the corresponding Fossil command. This only works on Unix. +** +** The "fossil shell" command is intended for use with SEE-enabled fossil. +** It allows multiple commands to be issued without having to reenter the +** crypto passphrase for each command. +*/ +#include "config.h" +#include "fshell.h" +#include <ctype.h> + +#ifndef _WIN32 +# include "linenoise.h" +# include <sys/types.h> +# include <sys/wait.h> +#endif + + +/* +** COMMAND: shell* +** +** Usage: %fossil shell +** +** Prompt for lines of input from stdin. Parse each line and evaluate +** it as a separate fossil command, in a child process. The initial +** "fossil" is omitted from each line. +** +** This command only works on unix-like platforms that support fork(). +** It is non-functional on Windows. +*/ +void shell_cmd(void){ +#ifdef _WIN32 + fossil_fatal("the 'shell' command is not supported on windows"); +#else + int nArg; + int mxArg = 0; + int n, i; + char **azArg = 0; + int fDebug; + pid_t childPid; + char *zLine = 0; + char *zPrompt = 0; + fDebug = find_option("debug", 0, 0)!=0; + db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0); + if(g.zRepositoryName!=0){ + zPrompt = mprintf("fossil (%z)> ", db_get("project-name","unnamed")); + }else{ + zPrompt = mprintf("fossil (no repo)> "); + } + db_close(0); + sqlite3_shutdown(); + linenoiseSetMultiLine(1); + while( (free(zLine), zLine = linenoise(zPrompt)) ){ + /* Remember shell history within the current session */ + linenoiseHistoryAdd(zLine); + + /* Parse the line of input */ + n = (int)strlen(zLine); + for(i=0, nArg=1; i<n; i++){ + while( fossil_isspace(zLine[i]) ){ i++; } + if( i>=n ) break; + if( nArg>=mxArg ){ + mxArg = nArg+10; + azArg = fossil_realloc(azArg, sizeof(char*)*mxArg); + if( nArg==1 ) azArg[0] = g.argv[0]; + } + if( zLine[i]=='"' || zLine[i]=='\'' ){ + char cQuote = zLine[i]; + i++; + azArg[nArg++] = &zLine[i]; + for(i++; i<n && zLine[i]!=cQuote; i++){} + }else{ + azArg[nArg++] = &zLine[i]; + while( i<n && !fossil_isspace(zLine[i]) ){ i++; } + } + zLine[i] = 0; + } + + /* If the --debug flag was used, display the parsed arguments */ + if( fDebug ){ + for(i=1; i<nArg; i++){ + fossil_print("argv[%d] = [%s]\n", i, azArg[i]); + } + } + + /* Special cases */ + if( nArg<2 ) continue; + if( fossil_strcmp(azArg[1],"exit")==0 ) break; + + /* Fork a process to handle the command */ + childPid = fork(); + if( childPid<0 ){ + printf("could not fork a child process to handle the command\n"); + fflush(stdout); + continue; + } + if( childPid==0 ){ + /* This is the child process */ + int main(int, char**); + fossil_main(nArg, azArg); + exit(0); + }else{ + /* The parent process */ + int status; + waitpid(childPid, &status, 0); + } + } + free(zPrompt); +#endif +} |
