|
1
|
/* |
|
2
|
** Copyright (c) 2016 D. Richard Hipp |
|
3
|
** |
|
4
|
** This program is free software; you can redistribute it and/or |
|
5
|
** modify it under the terms of the Simplified BSD License (also |
|
6
|
** known as the "2-Clause License" or "FreeBSD License".) |
|
7
|
|
|
8
|
** This program is distributed in the hope that it will be useful, |
|
9
|
** but without any warranty; without even the implied warranty of |
|
10
|
** merchantability or fitness for a particular purpose. |
|
11
|
** |
|
12
|
** Author contact information: |
|
13
|
** [email protected] |
|
14
|
** http://www.hwaci.com/drh/ |
|
15
|
** |
|
16
|
******************************************************************************* |
|
17
|
** |
|
18
|
** This module contains the code that implements the "fossil shell" command. |
|
19
|
** |
|
20
|
** The fossil shell prompts for lines of user input, then parses each line |
|
21
|
** after the fashion of a standard Bourne shell and forks a child process |
|
22
|
** to run the corresponding Fossil command. This only works on Unix. |
|
23
|
** |
|
24
|
** The "fossil shell" command is intended for use with SEE-enabled fossil. |
|
25
|
** It allows multiple commands to be issued without having to reenter the |
|
26
|
** crypto passphrase for each command. |
|
27
|
*/ |
|
28
|
#include "config.h" |
|
29
|
#include "fshell.h" |
|
30
|
#include <ctype.h> |
|
31
|
|
|
32
|
#ifndef _WIN32 |
|
33
|
# include "linenoise.h" |
|
34
|
# include <sys/types.h> |
|
35
|
# include <sys/wait.h> |
|
36
|
#endif |
|
37
|
|
|
38
|
|
|
39
|
/* |
|
40
|
** COMMAND: shell* |
|
41
|
** |
|
42
|
** Usage: %fossil shell |
|
43
|
** |
|
44
|
** Prompt for lines of input from stdin. Parse each line and evaluate |
|
45
|
** it as a separate fossil command, in a child process. The initial |
|
46
|
** "fossil" is omitted from each line. |
|
47
|
** |
|
48
|
** This command only works on unix-like platforms that support fork(). |
|
49
|
** It is non-functional on Windows. |
|
50
|
*/ |
|
51
|
void shell_cmd(void){ |
|
52
|
#ifdef _WIN32 |
|
53
|
fossil_fatal("the 'shell' command is not supported on windows"); |
|
54
|
#else |
|
55
|
int nArg; |
|
56
|
int mxArg = 0; |
|
57
|
int n, i; |
|
58
|
char **azArg = 0; |
|
59
|
int fDebug; |
|
60
|
pid_t childPid; |
|
61
|
char *zLine = 0; |
|
62
|
char *zPrompt = 0; |
|
63
|
fDebug = find_option("debug", 0, 0)!=0; |
|
64
|
db_find_and_open_repository(OPEN_ANY_SCHEMA|OPEN_OK_NOT_FOUND, 0); |
|
65
|
if(g.zRepositoryName!=0){ |
|
66
|
zPrompt = mprintf("fossil (%z)> ", db_get("project-name","unnamed")); |
|
67
|
}else{ |
|
68
|
zPrompt = mprintf("fossil (no repo)> "); |
|
69
|
} |
|
70
|
db_close(0); |
|
71
|
sqlite3_shutdown(); |
|
72
|
linenoiseSetMultiLine(1); |
|
73
|
while( (free(zLine), zLine = linenoise(zPrompt)) ){ |
|
74
|
/* Remember shell history within the current session */ |
|
75
|
linenoiseHistoryAdd(zLine); |
|
76
|
|
|
77
|
/* Parse the line of input */ |
|
78
|
n = (int)strlen(zLine); |
|
79
|
for(i=0, nArg=1; i<n; i++){ |
|
80
|
while( fossil_isspace(zLine[i]) ){ i++; } |
|
81
|
if( i>=n ) break; |
|
82
|
if( nArg>=mxArg ){ |
|
83
|
mxArg = nArg+10; |
|
84
|
azArg = fossil_realloc(azArg, sizeof(char*)*mxArg); |
|
85
|
if( nArg==1 ) azArg[0] = g.argv[0]; |
|
86
|
} |
|
87
|
if( zLine[i]=='"' || zLine[i]=='\'' ){ |
|
88
|
char cQuote = zLine[i]; |
|
89
|
i++; |
|
90
|
azArg[nArg++] = &zLine[i]; |
|
91
|
for(i++; i<n && zLine[i]!=cQuote; i++){} |
|
92
|
}else{ |
|
93
|
azArg[nArg++] = &zLine[i]; |
|
94
|
while( i<n && !fossil_isspace(zLine[i]) ){ i++; } |
|
95
|
} |
|
96
|
zLine[i] = 0; |
|
97
|
} |
|
98
|
|
|
99
|
/* If the --debug flag was used, display the parsed arguments */ |
|
100
|
if( fDebug ){ |
|
101
|
for(i=1; i<nArg; i++){ |
|
102
|
fossil_print("argv[%d] = [%s]\n", i, azArg[i]); |
|
103
|
} |
|
104
|
} |
|
105
|
|
|
106
|
/* Special cases */ |
|
107
|
if( nArg<2 ) continue; |
|
108
|
if( fossil_strcmp(azArg[1],"exit")==0 ) break; |
|
109
|
|
|
110
|
/* Fork a process to handle the command */ |
|
111
|
childPid = fork(); |
|
112
|
if( childPid<0 ){ |
|
113
|
printf("could not fork a child process to handle the command\n"); |
|
114
|
fflush(stdout); |
|
115
|
continue; |
|
116
|
} |
|
117
|
if( childPid==0 ){ |
|
118
|
/* This is the child process */ |
|
119
|
int main(int, char**); |
|
120
|
fossil_main(nArg, azArg); |
|
121
|
exit(0); |
|
122
|
}else{ |
|
123
|
/* The parent process */ |
|
124
|
int status; |
|
125
|
waitpid(childPid, &status, 0); |
|
126
|
} |
|
127
|
} |
|
128
|
free(zPrompt); |
|
129
|
#endif |
|
130
|
} |
|
131
|
|