Fossil SCM

Enhance the "fossil ui" command so that the REPOSITORY argument can be on a remote system.

drh 2021-06-30 20:33 trunk merge
Commit f3acbe429aa460c82591029efa4f37fb560ba8df58580d7f4e87904572e94eb7
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397397
iCol += 3;
398398
}
399399
}
400400
}
401401
402
-#if defined(_WIN32) || defined(WIN32)
403
-# undef popen
404
-# define popen _popen
405
-# undef pclose
406
-# define pclose _pclose
407
-#endif
408
-
409402
#if INTERFACE
410403
/*
411404
** An instance of the following object is used to send emails.
412405
*/
413406
struct AlertSender {
414407
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397 iCol += 3;
398 }
399 }
400 }
401
402 #if defined(_WIN32) || defined(WIN32)
403 # undef popen
404 # define popen _popen
405 # undef pclose
406 # define pclose _pclose
407 #endif
408
409 #if INTERFACE
410 /*
411 ** An instance of the following object is used to send emails.
412 */
413 struct AlertSender {
414
--- src/alerts.c
+++ src/alerts.c
@@ -397,17 +397,10 @@
397 iCol += 3;
398 }
399 }
400 }
401
 
 
 
 
 
 
 
402 #if INTERFACE
403 /*
404 ** An instance of the following object is used to send emails.
405 */
406 struct AlertSender {
407
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
6666
typedef int socklen_t;
6767
# endif
6868
# ifndef _WIN32
6969
# define _WIN32
7070
# endif
71
+# include <io.h>
72
+# include <fcntl.h>
73
+# undef popen
74
+# define popen _popen
75
+# undef pclose
76
+# define pclose _pclose
7177
#else
7278
# include <sys/types.h>
7379
# include <signal.h>
7480
# include <pwd.h>
7581
#endif
7682
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
66 typedef int socklen_t;
67 # endif
68 # ifndef _WIN32
69 # define _WIN32
70 # endif
 
 
 
 
 
 
71 #else
72 # include <sys/types.h>
73 # include <signal.h>
74 # include <pwd.h>
75 #endif
76
--- src/config.h
+++ src/config.h
@@ -66,10 +66,16 @@
66 typedef int socklen_t;
67 # endif
68 # ifndef _WIN32
69 # define _WIN32
70 # endif
71 # include <io.h>
72 # include <fcntl.h>
73 # undef popen
74 # define popen _popen
75 # undef pclose
76 # define pclose _pclose
77 #else
78 # include <sys/types.h>
79 # include <signal.h>
80 # include <pwd.h>
81 #endif
82
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
3838
int rid; /* Corresponding object in the BLOB table */
3939
char uuid[65]; /* The GIT hash name for this object */
4040
};
4141
#endif
4242
43
-#if defined(_WIN32) || defined(WIN32)
44
-# undef popen
45
-# define popen _popen
46
-# undef pclose
47
-# define pclose _pclose
48
-#endif
49
-
5043
/*
5144
** Output a "committer" record for the given user.
5245
** NOTE: the given user name may be an email itself.
5346
*/
5447
static void print_person(const char *zUser){
5548
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
38 int rid; /* Corresponding object in the BLOB table */
39 char uuid[65]; /* The GIT hash name for this object */
40 };
41 #endif
42
43 #if defined(_WIN32) || defined(WIN32)
44 # undef popen
45 # define popen _popen
46 # undef pclose
47 # define pclose _pclose
48 #endif
49
50 /*
51 ** Output a "committer" record for the given user.
52 ** NOTE: the given user name may be an email itself.
53 */
54 static void print_person(const char *zUser){
55
--- src/export.c
+++ src/export.c
@@ -38,17 +38,10 @@
38 int rid; /* Corresponding object in the BLOB table */
39 char uuid[65]; /* The GIT hash name for this object */
40 };
41 #endif
42
 
 
 
 
 
 
 
43 /*
44 ** Output a "committer" record for the given user.
45 ** NOTE: the given user name may be an email itself.
46 */
47 static void print_person(const char *zUser){
48
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
3030
*/
3131
#include "config.h"
3232
#include "extcgi.h"
3333
#include <assert.h>
3434
35
-#if defined(_WIN32) || defined(WIN32)
36
-# undef popen
37
-# define popen _popen
38
-# undef pclose
39
-# define pclose _pclose
40
-#endif
41
-
4235
/*
4336
** These are the environment variables that should be set for CGI
4437
** extension programs:
4538
*/
4639
static const char *azCgiEnv[] = {
4740
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
30 */
31 #include "config.h"
32 #include "extcgi.h"
33 #include <assert.h>
34
35 #if defined(_WIN32) || defined(WIN32)
36 # undef popen
37 # define popen _popen
38 # undef pclose
39 # define pclose _pclose
40 #endif
41
42 /*
43 ** These are the environment variables that should be set for CGI
44 ** extension programs:
45 */
46 static const char *azCgiEnv[] = {
47
--- src/extcgi.c
+++ src/extcgi.c
@@ -30,17 +30,10 @@
30 */
31 #include "config.h"
32 #include "extcgi.h"
33 #include <assert.h>
34
 
 
 
 
 
 
 
35 /*
36 ** These are the environment variables that should be set for CGI
37 ** extension programs:
38 */
39 static const char *azCgiEnv[] = {
40
--- src/http_transport.c
+++ src/http_transport.c
@@ -93,13 +93,13 @@
9393
9494
/*
9595
** Default SSH command
9696
*/
9797
#if 0 /* was: defined(_WIN32). Windows generally has ssh now. */
98
-static const char zDefaultSshCmd[] = "plink -ssh -T";
98
+static const char zDefaultSshCmd[] = "plink -ssh";
9999
#else
100
-static const char zDefaultSshCmd[] = "ssh -e none -T";
100
+static const char zDefaultSshCmd[] = "ssh -e none";
101101
#endif
102102
103103
/*
104104
** Initialize a Blob to the name of the configured SSH command.
105105
*/
@@ -122,11 +122,11 @@
122122
socket_ssh_resolve_addr(pUrlData);
123123
transport_ssh_command(&zCmd);
124124
if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
125125
blob_appendf(&zCmd, " -p %d", pUrlData->port);
126126
}
127
- blob_appendf(&zCmd, " --"); /* End of switches */
127
+ blob_appendf(&zCmd, " -T --"); /* End of switches */
128128
if( pUrlData->user && pUrlData->user[0] ){
129129
zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
130130
blob_append_escaped_arg(&zCmd, zHost, 0);
131131
fossil_free(zHost);
132132
}else{
133133
--- src/http_transport.c
+++ src/http_transport.c
@@ -93,13 +93,13 @@
93
94 /*
95 ** Default SSH command
96 */
97 #if 0 /* was: defined(_WIN32). Windows generally has ssh now. */
98 static const char zDefaultSshCmd[] = "plink -ssh -T";
99 #else
100 static const char zDefaultSshCmd[] = "ssh -e none -T";
101 #endif
102
103 /*
104 ** Initialize a Blob to the name of the configured SSH command.
105 */
@@ -122,11 +122,11 @@
122 socket_ssh_resolve_addr(pUrlData);
123 transport_ssh_command(&zCmd);
124 if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
125 blob_appendf(&zCmd, " -p %d", pUrlData->port);
126 }
127 blob_appendf(&zCmd, " --"); /* End of switches */
128 if( pUrlData->user && pUrlData->user[0] ){
129 zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
130 blob_append_escaped_arg(&zCmd, zHost, 0);
131 fossil_free(zHost);
132 }else{
133
--- src/http_transport.c
+++ src/http_transport.c
@@ -93,13 +93,13 @@
93
94 /*
95 ** Default SSH command
96 */
97 #if 0 /* was: defined(_WIN32). Windows generally has ssh now. */
98 static const char zDefaultSshCmd[] = "plink -ssh";
99 #else
100 static const char zDefaultSshCmd[] = "ssh -e none";
101 #endif
102
103 /*
104 ** Initialize a Blob to the name of the configured SSH command.
105 */
@@ -122,11 +122,11 @@
122 socket_ssh_resolve_addr(pUrlData);
123 transport_ssh_command(&zCmd);
124 if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
125 blob_appendf(&zCmd, " -p %d", pUrlData->port);
126 }
127 blob_appendf(&zCmd, " -T --"); /* End of switches */
128 if( pUrlData->user && pUrlData->user[0] ){
129 zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
130 blob_append_escaped_arg(&zCmd, zHost, 0);
131 fossil_free(zHost);
132 }else{
133
+76 -25
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
28162816
** also present.
28172817
**
28182818
** If the REPOSITORY is a directory name which is the root of a
28192819
** checkout, it will chdir to that directory and, unless overridden by
28202820
** the --page option, select the current checkout version in the
2821
-** timeline by default.
2821
+** timeline by default. This only works for the "fossil ui" command,
2822
+** not the "fossil server" command.
2823
+**
2824
+** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
2825
+** the command is run on the remote host specified and the results are
2826
+** tunneled back to the local host via SSH. This feature only works for
2827
+** the "fossil ui" command, not the "fossil server" command.
28222828
**
2823
-** For the special case REPOSITORY name of "/", the list global configuration
2829
+** For the special case REPOSITORY name of "/", the global configuration
28242830
** database is consulted for a list of all known repositories. The --repolist
28252831
** option is implied by this special case. See also the "fossil all ui"
28262832
** command.
28272833
**
28282834
** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
28552861
** and bundled modes might result in a single
28562862
** amalgamated script or several, but both approaches
28572863
** result in fewer HTTP requests than the separate mode.
28582864
** --max-latency N Do not let any single HTTP request run for more than N
28592865
** seconds (only works on unix)
2866
+** --nobrowser Do not automatically launch a web-browser for the
2867
+** "fossil ui" command.
28602868
** --nocompress Do not compress HTTP replies
28612869
** --nojail Drop root privileges but do not enter the chroot jail
28622870
** --nossl signal that no SSL connections are available (Always
28632871
** set by default for the "ui" command)
28642872
** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
28902898
int allowRepoList; /* List repositories on URL "/" */
28912899
const char *zAltBase; /* Argument to the --baseurl option */
28922900
const char *zFileGlob; /* Static content must match this */
28932901
char *zIpAddr = 0; /* Bind to this IP address */
28942902
int fCreate = 0; /* The --create flag */
2903
+ int fNoBrowser = 0; /* Do not auto-launch web-browser */
28952904
const char *zInitPage = 0; /* Start on this page. --page option */
28962905
int findServerArg = 2; /* argv index for find_server_repository() */
2906
+ char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2907
+
28972908
28982909
#if defined(_WIN32)
28992910
const char *zStopperFile; /* Name of file used to terminate server */
29002911
zStopperFile = find_option("stopper", 0, 1);
29012912
#endif
@@ -2933,10 +2944,11 @@
29332944
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
29342945
if( zAltBase ){
29352946
set_base_url(zAltBase);
29362947
}
29372948
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2949
+ fNoBrowser = find_option("nobrowser", 0, 0)!=0;
29382950
if( find_option("https",0,0)!=0 ){
29392951
cgi_replace_parameter("HTTPS","on");
29402952
}
29412953
if( find_option("localhost", 0, 0)!=0 ){
29422954
flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
29632975
fCreate = 0;
29642976
g.argv[2] = 0;
29652977
--g.argc;
29662978
}
29672979
}
2980
+ if( isUiCmd && 3==g.argc
2981
+ && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
2982
+ ){
2983
+ /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
2984
+ const char *zRepoTail = file_skip_userhost(g.argv[2]);
2985
+ unsigned x;
2986
+ int n;
2987
+ sqlite3_randomness(2,&x);
2988
+ zPort = mprintf("%d", 8100+(x%32000));
2989
+ n = (int)(zRepoTail - g.argv[2]) - 1;
2990
+ zRemote = mprintf("%.*s", n, g.argv[2]);
2991
+ g.argv[2] = (char*)zRepoTail;
2992
+ }
29682993
if( isUiCmd ){
29692994
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
29702995
g.useLocalauth = 1;
29712996
allowRepoList = 1;
29722997
}
2973
- find_server_repository(findServerArg, fCreate);
2998
+ if( !zRemote ){
2999
+ find_server_repository(findServerArg, fCreate);
3000
+ }
29743001
if( zInitPage==0 ){
29753002
if( isUiCmd && g.localOpen ){
29763003
zInitPage = "timeline?c=current";
29773004
}else{
29783005
zInitPage = "";
@@ -2994,25 +3021,62 @@
29943021
iPort = mxPort = atoi(zPort);
29953022
}else{
29963023
iPort = db_get_int("http-port", 8080);
29973024
mxPort = iPort+100;
29983025
}
2999
-#if !defined(_WIN32)
3000
- /* Unix implementation */
3001
- if( isUiCmd ){
3026
+ if( isUiCmd && !fNoBrowser ){
3027
+ char *zBrowserArg;
30023028
zBrowser = fossil_web_browser();
30033029
if( zIpAddr==0 ){
3004
- zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
3005
- zBrowser, zInitPage);
3030
+ zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
30063031
}else if( strchr(zIpAddr,':') ){
3007
- zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
3008
- zBrowser, zIpAddr, zInitPage);
3032
+ zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
30093033
}else{
3010
- zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
3011
- zBrowser, zIpAddr, zInitPage);
3034
+ zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3035
+ }
3036
+#ifdef _WIN32
3037
+ zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3038
+#else
3039
+ zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3040
+#endif
3041
+ fossil_free(zBrowserArg);
3042
+ }
3043
+ if( zRemote ){
3044
+ /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3045
+ ** "fossil ui --nobrowser" on the remote system and to set up a
3046
+ ** tunnel from the local machine to the remote. */
3047
+ FILE *sshIn;
3048
+ Blob ssh;
3049
+ char zLine[1000];
3050
+ blob_init(&ssh, 0, 0);
3051
+ transport_ssh_command(&ssh);
3052
+ blob_appendf(&ssh,
3053
+ " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
3054
+ " fossil ui --nobrowser --localauth --port %d %$",
3055
+ iPort, iPort, zRemote, iPort, g.argv[2]);
3056
+ fossil_print("%s\n", blob_str(&ssh));
3057
+ sshIn = popen(blob_str(&ssh), "r");
3058
+ if( sshIn==0 ){
3059
+ fossil_fatal("unable to %s", blob_str(&ssh));
3060
+ }
3061
+ while( fgets(zLine, sizeof(zLine), sshIn) ){
3062
+ fputs(zLine, stdout);
3063
+ fflush(stdout);
3064
+ if( zBrowserCmd ){
3065
+ char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3066
+ fossil_system(zCmd);
3067
+ fossil_free(zCmd);
3068
+ fossil_free(zBrowserCmd);
3069
+ zBrowserCmd = 0;
3070
+ }
30123071
}
3072
+ pclose(sshIn);
3073
+ fossil_free(zBrowserCmd);
3074
+ return;
30133075
}
3076
+#if !defined(_WIN32)
3077
+ /* Unix implementation */
30143078
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30153079
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30163080
db_close(1);
30173081
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
30183082
fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
30593123
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
30603124
getpid());
30613125
}
30623126
#else
30633127
/* Win32 implementation */
3064
- if( isUiCmd ){
3065
- zBrowser = fossil_web_browser();
3066
- if( zIpAddr==0 ){
3067
- zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3068
- zBrowser, zInitPage);
3069
- }else if( strchr(zIpAddr,':') ){
3070
- zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3071
- zBrowser, zIpAddr, zInitPage);
3072
- }else{
3073
- zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3074
- zBrowser, zIpAddr, zInitPage);
3075
- }
3076
- }
30773128
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30783129
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30793130
db_close(1);
30803131
if( allowRepoList ){
30813132
flags |= HTTP_SERVER_REPOLIST;
30823133
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
2816 ** also present.
2817 **
2818 ** If the REPOSITORY is a directory name which is the root of a
2819 ** checkout, it will chdir to that directory and, unless overridden by
2820 ** the --page option, select the current checkout version in the
2821 ** timeline by default.
 
 
 
 
 
 
2822 **
2823 ** For the special case REPOSITORY name of "/", the list global configuration
2824 ** database is consulted for a list of all known repositories. The --repolist
2825 ** option is implied by this special case. See also the "fossil all ui"
2826 ** command.
2827 **
2828 ** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
2855 ** and bundled modes might result in a single
2856 ** amalgamated script or several, but both approaches
2857 ** result in fewer HTTP requests than the separate mode.
2858 ** --max-latency N Do not let any single HTTP request run for more than N
2859 ** seconds (only works on unix)
 
 
2860 ** --nocompress Do not compress HTTP replies
2861 ** --nojail Drop root privileges but do not enter the chroot jail
2862 ** --nossl signal that no SSL connections are available (Always
2863 ** set by default for the "ui" command)
2864 ** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
2890 int allowRepoList; /* List repositories on URL "/" */
2891 const char *zAltBase; /* Argument to the --baseurl option */
2892 const char *zFileGlob; /* Static content must match this */
2893 char *zIpAddr = 0; /* Bind to this IP address */
2894 int fCreate = 0; /* The --create flag */
 
2895 const char *zInitPage = 0; /* Start on this page. --page option */
2896 int findServerArg = 2; /* argv index for find_server_repository() */
 
 
2897
2898 #if defined(_WIN32)
2899 const char *zStopperFile; /* Name of file used to terminate server */
2900 zStopperFile = find_option("stopper", 0, 1);
2901 #endif
@@ -2933,10 +2944,11 @@
2933 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2934 if( zAltBase ){
2935 set_base_url(zAltBase);
2936 }
2937 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
 
2938 if( find_option("https",0,0)!=0 ){
2939 cgi_replace_parameter("HTTPS","on");
2940 }
2941 if( find_option("localhost", 0, 0)!=0 ){
2942 flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
2963 fCreate = 0;
2964 g.argv[2] = 0;
2965 --g.argc;
2966 }
2967 }
 
 
 
 
 
 
 
 
 
 
 
 
 
2968 if( isUiCmd ){
2969 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2970 g.useLocalauth = 1;
2971 allowRepoList = 1;
2972 }
2973 find_server_repository(findServerArg, fCreate);
 
 
2974 if( zInitPage==0 ){
2975 if( isUiCmd && g.localOpen ){
2976 zInitPage = "timeline?c=current";
2977 }else{
2978 zInitPage = "";
@@ -2994,25 +3021,62 @@
2994 iPort = mxPort = atoi(zPort);
2995 }else{
2996 iPort = db_get_int("http-port", 8080);
2997 mxPort = iPort+100;
2998 }
2999 #if !defined(_WIN32)
3000 /* Unix implementation */
3001 if( isUiCmd ){
3002 zBrowser = fossil_web_browser();
3003 if( zIpAddr==0 ){
3004 zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
3005 zBrowser, zInitPage);
3006 }else if( strchr(zIpAddr,':') ){
3007 zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
3008 zBrowser, zIpAddr, zInitPage);
3009 }else{
3010 zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
3011 zBrowser, zIpAddr, zInitPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3012 }
 
 
 
3013 }
 
 
3014 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3015 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3016 db_close(1);
3017 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3018 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
3059 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3060 getpid());
3061 }
3062 #else
3063 /* Win32 implementation */
3064 if( isUiCmd ){
3065 zBrowser = fossil_web_browser();
3066 if( zIpAddr==0 ){
3067 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3068 zBrowser, zInitPage);
3069 }else if( strchr(zIpAddr,':') ){
3070 zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3071 zBrowser, zIpAddr, zInitPage);
3072 }else{
3073 zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3074 zBrowser, zIpAddr, zInitPage);
3075 }
3076 }
3077 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3078 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3079 db_close(1);
3080 if( allowRepoList ){
3081 flags |= HTTP_SERVER_REPOLIST;
3082
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
2816 ** also present.
2817 **
2818 ** If the REPOSITORY is a directory name which is the root of a
2819 ** checkout, it will chdir to that directory and, unless overridden by
2820 ** the --page option, select the current checkout version in the
2821 ** timeline by default. This only works for the "fossil ui" command,
2822 ** not the "fossil server" command.
2823 **
2824 ** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
2825 ** the command is run on the remote host specified and the results are
2826 ** tunneled back to the local host via SSH. This feature only works for
2827 ** the "fossil ui" command, not the "fossil server" command.
2828 **
2829 ** For the special case REPOSITORY name of "/", the global configuration
2830 ** database is consulted for a list of all known repositories. The --repolist
2831 ** option is implied by this special case. See also the "fossil all ui"
2832 ** command.
2833 **
2834 ** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
2861 ** and bundled modes might result in a single
2862 ** amalgamated script or several, but both approaches
2863 ** result in fewer HTTP requests than the separate mode.
2864 ** --max-latency N Do not let any single HTTP request run for more than N
2865 ** seconds (only works on unix)
2866 ** --nobrowser Do not automatically launch a web-browser for the
2867 ** "fossil ui" command.
2868 ** --nocompress Do not compress HTTP replies
2869 ** --nojail Drop root privileges but do not enter the chroot jail
2870 ** --nossl signal that no SSL connections are available (Always
2871 ** set by default for the "ui" command)
2872 ** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
2898 int allowRepoList; /* List repositories on URL "/" */
2899 const char *zAltBase; /* Argument to the --baseurl option */
2900 const char *zFileGlob; /* Static content must match this */
2901 char *zIpAddr = 0; /* Bind to this IP address */
2902 int fCreate = 0; /* The --create flag */
2903 int fNoBrowser = 0; /* Do not auto-launch web-browser */
2904 const char *zInitPage = 0; /* Start on this page. --page option */
2905 int findServerArg = 2; /* argv index for find_server_repository() */
2906 char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2907
2908
2909 #if defined(_WIN32)
2910 const char *zStopperFile; /* Name of file used to terminate server */
2911 zStopperFile = find_option("stopper", 0, 1);
2912 #endif
@@ -2933,10 +2944,11 @@
2944 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2945 if( zAltBase ){
2946 set_base_url(zAltBase);
2947 }
2948 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2949 fNoBrowser = find_option("nobrowser", 0, 0)!=0;
2950 if( find_option("https",0,0)!=0 ){
2951 cgi_replace_parameter("HTTPS","on");
2952 }
2953 if( find_option("localhost", 0, 0)!=0 ){
2954 flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
2975 fCreate = 0;
2976 g.argv[2] = 0;
2977 --g.argc;
2978 }
2979 }
2980 if( isUiCmd && 3==g.argc
2981 && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
2982 ){
2983 /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
2984 const char *zRepoTail = file_skip_userhost(g.argv[2]);
2985 unsigned x;
2986 int n;
2987 sqlite3_randomness(2,&x);
2988 zPort = mprintf("%d", 8100+(x%32000));
2989 n = (int)(zRepoTail - g.argv[2]) - 1;
2990 zRemote = mprintf("%.*s", n, g.argv[2]);
2991 g.argv[2] = (char*)zRepoTail;
2992 }
2993 if( isUiCmd ){
2994 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2995 g.useLocalauth = 1;
2996 allowRepoList = 1;
2997 }
2998 if( !zRemote ){
2999 find_server_repository(findServerArg, fCreate);
3000 }
3001 if( zInitPage==0 ){
3002 if( isUiCmd && g.localOpen ){
3003 zInitPage = "timeline?c=current";
3004 }else{
3005 zInitPage = "";
@@ -2994,25 +3021,62 @@
3021 iPort = mxPort = atoi(zPort);
3022 }else{
3023 iPort = db_get_int("http-port", 8080);
3024 mxPort = iPort+100;
3025 }
3026 if( isUiCmd && !fNoBrowser ){
3027 char *zBrowserArg;
 
3028 zBrowser = fossil_web_browser();
3029 if( zIpAddr==0 ){
3030 zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
 
3031 }else if( strchr(zIpAddr,':') ){
3032 zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
 
3033 }else{
3034 zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3035 }
3036 #ifdef _WIN32
3037 zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3038 #else
3039 zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3040 #endif
3041 fossil_free(zBrowserArg);
3042 }
3043 if( zRemote ){
3044 /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3045 ** "fossil ui --nobrowser" on the remote system and to set up a
3046 ** tunnel from the local machine to the remote. */
3047 FILE *sshIn;
3048 Blob ssh;
3049 char zLine[1000];
3050 blob_init(&ssh, 0, 0);
3051 transport_ssh_command(&ssh);
3052 blob_appendf(&ssh,
3053 " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
3054 " fossil ui --nobrowser --localauth --port %d %$",
3055 iPort, iPort, zRemote, iPort, g.argv[2]);
3056 fossil_print("%s\n", blob_str(&ssh));
3057 sshIn = popen(blob_str(&ssh), "r");
3058 if( sshIn==0 ){
3059 fossil_fatal("unable to %s", blob_str(&ssh));
3060 }
3061 while( fgets(zLine, sizeof(zLine), sshIn) ){
3062 fputs(zLine, stdout);
3063 fflush(stdout);
3064 if( zBrowserCmd ){
3065 char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3066 fossil_system(zCmd);
3067 fossil_free(zCmd);
3068 fossil_free(zBrowserCmd);
3069 zBrowserCmd = 0;
3070 }
3071 }
3072 pclose(sshIn);
3073 fossil_free(zBrowserCmd);
3074 return;
3075 }
3076 #if !defined(_WIN32)
3077 /* Unix implementation */
3078 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3079 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3080 db_close(1);
3081 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3082 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
3123 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3124 getpid());
3125 }
3126 #else
3127 /* Win32 implementation */
 
 
 
 
 
 
 
 
 
 
 
 
 
3128 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3129 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3130 db_close(1);
3131 if( allowRepoList ){
3132 flags |= HTTP_SERVER_REPOLIST;
3133
+76 -25
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
28162816
** also present.
28172817
**
28182818
** If the REPOSITORY is a directory name which is the root of a
28192819
** checkout, it will chdir to that directory and, unless overridden by
28202820
** the --page option, select the current checkout version in the
2821
-** timeline by default.
2821
+** timeline by default. This only works for the "fossil ui" command,
2822
+** not the "fossil server" command.
2823
+**
2824
+** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
2825
+** the command is run on the remote host specified and the results are
2826
+** tunneled back to the local host via SSH. This feature only works for
2827
+** the "fossil ui" command, not the "fossil server" command.
28222828
**
2823
-** For the special case REPOSITORY name of "/", the list global configuration
2829
+** For the special case REPOSITORY name of "/", the global configuration
28242830
** database is consulted for a list of all known repositories. The --repolist
28252831
** option is implied by this special case. See also the "fossil all ui"
28262832
** command.
28272833
**
28282834
** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
28552861
** and bundled modes might result in a single
28562862
** amalgamated script or several, but both approaches
28572863
** result in fewer HTTP requests than the separate mode.
28582864
** --max-latency N Do not let any single HTTP request run for more than N
28592865
** seconds (only works on unix)
2866
+** --nobrowser Do not automatically launch a web-browser for the
2867
+** "fossil ui" command.
28602868
** --nocompress Do not compress HTTP replies
28612869
** --nojail Drop root privileges but do not enter the chroot jail
28622870
** --nossl signal that no SSL connections are available (Always
28632871
** set by default for the "ui" command)
28642872
** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
28902898
int allowRepoList; /* List repositories on URL "/" */
28912899
const char *zAltBase; /* Argument to the --baseurl option */
28922900
const char *zFileGlob; /* Static content must match this */
28932901
char *zIpAddr = 0; /* Bind to this IP address */
28942902
int fCreate = 0; /* The --create flag */
2903
+ int fNoBrowser = 0; /* Do not auto-launch web-browser */
28952904
const char *zInitPage = 0; /* Start on this page. --page option */
28962905
int findServerArg = 2; /* argv index for find_server_repository() */
2906
+ char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2907
+
28972908
28982909
#if defined(_WIN32)
28992910
const char *zStopperFile; /* Name of file used to terminate server */
29002911
zStopperFile = find_option("stopper", 0, 1);
29012912
#endif
@@ -2933,10 +2944,11 @@
29332944
if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
29342945
if( zAltBase ){
29352946
set_base_url(zAltBase);
29362947
}
29372948
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2949
+ fNoBrowser = find_option("nobrowser", 0, 0)!=0;
29382950
if( find_option("https",0,0)!=0 ){
29392951
cgi_replace_parameter("HTTPS","on");
29402952
}
29412953
if( find_option("localhost", 0, 0)!=0 ){
29422954
flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
29632975
fCreate = 0;
29642976
g.argv[2] = 0;
29652977
--g.argc;
29662978
}
29672979
}
2980
+ if( isUiCmd && 3==g.argc
2981
+ && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
2982
+ ){
2983
+ /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
2984
+ const char *zRepoTail = file_skip_userhost(g.argv[2]);
2985
+ unsigned x;
2986
+ int n;
2987
+ sqlite3_randomness(2,&x);
2988
+ zPort = mprintf("%d", 8100+(x%32000));
2989
+ n = (int)(zRepoTail - g.argv[2]) - 1;
2990
+ zRemote = mprintf("%.*s", n, g.argv[2]);
2991
+ g.argv[2] = (char*)zRepoTail;
2992
+ }
29682993
if( isUiCmd ){
29692994
flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
29702995
g.useLocalauth = 1;
29712996
allowRepoList = 1;
29722997
}
2973
- find_server_repository(findServerArg, fCreate);
2998
+ if( !zRemote ){
2999
+ find_server_repository(findServerArg, fCreate);
3000
+ }
29743001
if( zInitPage==0 ){
29753002
if( isUiCmd && g.localOpen ){
29763003
zInitPage = "timeline?c=current";
29773004
}else{
29783005
zInitPage = "";
@@ -2994,25 +3021,62 @@
29943021
iPort = mxPort = atoi(zPort);
29953022
}else{
29963023
iPort = db_get_int("http-port", 8080);
29973024
mxPort = iPort+100;
29983025
}
2999
-#if !defined(_WIN32)
3000
- /* Unix implementation */
3001
- if( isUiCmd ){
3026
+ if( isUiCmd && !fNoBrowser ){
3027
+ char *zBrowserArg;
30023028
zBrowser = fossil_web_browser();
30033029
if( zIpAddr==0 ){
3004
- zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
3005
- zBrowser, zInitPage);
3030
+ zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
30063031
}else if( strchr(zIpAddr,':') ){
3007
- zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
3008
- zBrowser, zIpAddr, zInitPage);
3032
+ zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
30093033
}else{
3010
- zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
3011
- zBrowser, zIpAddr, zInitPage);
3034
+ zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3035
+ }
3036
+#ifdef _WIN32
3037
+ zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3038
+#else
3039
+ zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3040
+#endif
3041
+ fossil_free(zBrowserArg);
3042
+ }
3043
+ if( zRemote ){
3044
+ /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3045
+ ** "fossil ui --nobrowser" on the remote system and to set up a
3046
+ ** tunnel from the local machine to the remote. */
3047
+ FILE *sshIn;
3048
+ Blob ssh;
3049
+ char zLine[1000];
3050
+ blob_init(&ssh, 0, 0);
3051
+ transport_ssh_command(&ssh);
3052
+ blob_appendf(&ssh,
3053
+ " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
3054
+ " fossil ui --nobrowser --localauth --port %d %$",
3055
+ iPort, iPort, zRemote, iPort, g.argv[2]);
3056
+ fossil_print("%s\n", blob_str(&ssh));
3057
+ sshIn = popen(blob_str(&ssh), "r");
3058
+ if( sshIn==0 ){
3059
+ fossil_fatal("unable to %s", blob_str(&ssh));
3060
+ }
3061
+ while( fgets(zLine, sizeof(zLine), sshIn) ){
3062
+ fputs(zLine, stdout);
3063
+ fflush(stdout);
3064
+ if( zBrowserCmd ){
3065
+ char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3066
+ fossil_system(zCmd);
3067
+ fossil_free(zCmd);
3068
+ fossil_free(zBrowserCmd);
3069
+ zBrowserCmd = 0;
3070
+ }
30123071
}
3072
+ pclose(sshIn);
3073
+ fossil_free(zBrowserCmd);
3074
+ return;
30133075
}
3076
+#if !defined(_WIN32)
3077
+ /* Unix implementation */
30143078
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30153079
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30163080
db_close(1);
30173081
if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
30183082
fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
30593123
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
30603124
getpid());
30613125
}
30623126
#else
30633127
/* Win32 implementation */
3064
- if( isUiCmd ){
3065
- zBrowser = fossil_web_browser();
3066
- if( zIpAddr==0 ){
3067
- zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3068
- zBrowser, zInitPage);
3069
- }else if( strchr(zIpAddr,':') ){
3070
- zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3071
- zBrowser, zIpAddr, zInitPage);
3072
- }else{
3073
- zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3074
- zBrowser, zIpAddr, zInitPage);
3075
- }
3076
- }
30773128
if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
30783129
if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
30793130
db_close(1);
30803131
if( allowRepoList ){
30813132
flags |= HTTP_SERVER_REPOLIST;
30823133
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
2816 ** also present.
2817 **
2818 ** If the REPOSITORY is a directory name which is the root of a
2819 ** checkout, it will chdir to that directory and, unless overridden by
2820 ** the --page option, select the current checkout version in the
2821 ** timeline by default.
 
 
 
 
 
 
2822 **
2823 ** For the special case REPOSITORY name of "/", the list global configuration
2824 ** database is consulted for a list of all known repositories. The --repolist
2825 ** option is implied by this special case. See also the "fossil all ui"
2826 ** command.
2827 **
2828 ** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
2855 ** and bundled modes might result in a single
2856 ** amalgamated script or several, but both approaches
2857 ** result in fewer HTTP requests than the separate mode.
2858 ** --max-latency N Do not let any single HTTP request run for more than N
2859 ** seconds (only works on unix)
 
 
2860 ** --nocompress Do not compress HTTP replies
2861 ** --nojail Drop root privileges but do not enter the chroot jail
2862 ** --nossl signal that no SSL connections are available (Always
2863 ** set by default for the "ui" command)
2864 ** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
2890 int allowRepoList; /* List repositories on URL "/" */
2891 const char *zAltBase; /* Argument to the --baseurl option */
2892 const char *zFileGlob; /* Static content must match this */
2893 char *zIpAddr = 0; /* Bind to this IP address */
2894 int fCreate = 0; /* The --create flag */
 
2895 const char *zInitPage = 0; /* Start on this page. --page option */
2896 int findServerArg = 2; /* argv index for find_server_repository() */
 
 
2897
2898 #if defined(_WIN32)
2899 const char *zStopperFile; /* Name of file used to terminate server */
2900 zStopperFile = find_option("stopper", 0, 1);
2901 #endif
@@ -2933,10 +2944,11 @@
2933 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2934 if( zAltBase ){
2935 set_base_url(zAltBase);
2936 }
2937 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
 
2938 if( find_option("https",0,0)!=0 ){
2939 cgi_replace_parameter("HTTPS","on");
2940 }
2941 if( find_option("localhost", 0, 0)!=0 ){
2942 flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
2963 fCreate = 0;
2964 g.argv[2] = 0;
2965 --g.argc;
2966 }
2967 }
 
 
 
 
 
 
 
 
 
 
 
 
 
2968 if( isUiCmd ){
2969 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2970 g.useLocalauth = 1;
2971 allowRepoList = 1;
2972 }
2973 find_server_repository(findServerArg, fCreate);
 
 
2974 if( zInitPage==0 ){
2975 if( isUiCmd && g.localOpen ){
2976 zInitPage = "timeline?c=current";
2977 }else{
2978 zInitPage = "";
@@ -2994,25 +3021,62 @@
2994 iPort = mxPort = atoi(zPort);
2995 }else{
2996 iPort = db_get_int("http-port", 8080);
2997 mxPort = iPort+100;
2998 }
2999 #if !defined(_WIN32)
3000 /* Unix implementation */
3001 if( isUiCmd ){
3002 zBrowser = fossil_web_browser();
3003 if( zIpAddr==0 ){
3004 zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &",
3005 zBrowser, zInitPage);
3006 }else if( strchr(zIpAddr,':') ){
3007 zBrowserCmd = mprintf("%s \"http://[%s]:%%d/%s\" &",
3008 zBrowser, zIpAddr, zInitPage);
3009 }else{
3010 zBrowserCmd = mprintf("%s \"http://%s:%%d/%s\" &",
3011 zBrowser, zIpAddr, zInitPage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3012 }
 
 
 
3013 }
 
 
3014 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3015 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3016 db_close(1);
3017 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3018 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
3059 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3060 getpid());
3061 }
3062 #else
3063 /* Win32 implementation */
3064 if( isUiCmd ){
3065 zBrowser = fossil_web_browser();
3066 if( zIpAddr==0 ){
3067 zBrowserCmd = mprintf("%s http://localhost:%%d/%s &",
3068 zBrowser, zInitPage);
3069 }else if( strchr(zIpAddr,':') ){
3070 zBrowserCmd = mprintf("%s http://[%s]:%%d/%s &",
3071 zBrowser, zIpAddr, zInitPage);
3072 }else{
3073 zBrowserCmd = mprintf("%s http://%s:%%d/%s &",
3074 zBrowser, zIpAddr, zInitPage);
3075 }
3076 }
3077 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3078 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3079 db_close(1);
3080 if( allowRepoList ){
3081 flags |= HTTP_SERVER_REPOLIST;
3082
--- src/main.c
+++ src/main.c
@@ -2816,13 +2816,19 @@
2816 ** also present.
2817 **
2818 ** If the REPOSITORY is a directory name which is the root of a
2819 ** checkout, it will chdir to that directory and, unless overridden by
2820 ** the --page option, select the current checkout version in the
2821 ** timeline by default. This only works for the "fossil ui" command,
2822 ** not the "fossil server" command.
2823 **
2824 ** If the REPOSITORY argument has a "HOST:" or "USER@HOST:" prefix, then
2825 ** the command is run on the remote host specified and the results are
2826 ** tunneled back to the local host via SSH. This feature only works for
2827 ** the "fossil ui" command, not the "fossil server" command.
2828 **
2829 ** For the special case REPOSITORY name of "/", the global configuration
2830 ** database is consulted for a list of all known repositories. The --repolist
2831 ** option is implied by this special case. See also the "fossil all ui"
2832 ** command.
2833 **
2834 ** By default, the "ui" command provides full administrative access without
@@ -2855,10 +2861,12 @@
2861 ** and bundled modes might result in a single
2862 ** amalgamated script or several, but both approaches
2863 ** result in fewer HTTP requests than the separate mode.
2864 ** --max-latency N Do not let any single HTTP request run for more than N
2865 ** seconds (only works on unix)
2866 ** --nobrowser Do not automatically launch a web-browser for the
2867 ** "fossil ui" command.
2868 ** --nocompress Do not compress HTTP replies
2869 ** --nojail Drop root privileges but do not enter the chroot jail
2870 ** --nossl signal that no SSL connections are available (Always
2871 ** set by default for the "ui" command)
2872 ** --notfound URL Redirect
@@ -2890,12 +2898,15 @@
2898 int allowRepoList; /* List repositories on URL "/" */
2899 const char *zAltBase; /* Argument to the --baseurl option */
2900 const char *zFileGlob; /* Static content must match this */
2901 char *zIpAddr = 0; /* Bind to this IP address */
2902 int fCreate = 0; /* The --create flag */
2903 int fNoBrowser = 0; /* Do not auto-launch web-browser */
2904 const char *zInitPage = 0; /* Start on this page. --page option */
2905 int findServerArg = 2; /* argv index for find_server_repository() */
2906 char *zRemote = 0; /* Remote host on which to run "fossil ui" */
2907
2908
2909 #if defined(_WIN32)
2910 const char *zStopperFile; /* Name of file used to terminate server */
2911 zStopperFile = find_option("stopper", 0, 1);
2912 #endif
@@ -2933,10 +2944,11 @@
2944 if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
2945 if( zAltBase ){
2946 set_base_url(zAltBase);
2947 }
2948 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
2949 fNoBrowser = find_option("nobrowser", 0, 0)!=0;
2950 if( find_option("https",0,0)!=0 ){
2951 cgi_replace_parameter("HTTPS","on");
2952 }
2953 if( find_option("localhost", 0, 0)!=0 ){
2954 flags |= HTTP_SERVER_LOCALHOST;
@@ -2963,16 +2975,31 @@
2975 fCreate = 0;
2976 g.argv[2] = 0;
2977 --g.argc;
2978 }
2979 }
2980 if( isUiCmd && 3==g.argc
2981 && (zRemote = (char*)file_skip_userhost(g.argv[2]))!=0
2982 ){
2983 /* The REPOSITORY argument has a USER@HOST: or HOST: prefix */
2984 const char *zRepoTail = file_skip_userhost(g.argv[2]);
2985 unsigned x;
2986 int n;
2987 sqlite3_randomness(2,&x);
2988 zPort = mprintf("%d", 8100+(x%32000));
2989 n = (int)(zRepoTail - g.argv[2]) - 1;
2990 zRemote = mprintf("%.*s", n, g.argv[2]);
2991 g.argv[2] = (char*)zRepoTail;
2992 }
2993 if( isUiCmd ){
2994 flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
2995 g.useLocalauth = 1;
2996 allowRepoList = 1;
2997 }
2998 if( !zRemote ){
2999 find_server_repository(findServerArg, fCreate);
3000 }
3001 if( zInitPage==0 ){
3002 if( isUiCmd && g.localOpen ){
3003 zInitPage = "timeline?c=current";
3004 }else{
3005 zInitPage = "";
@@ -2994,25 +3021,62 @@
3021 iPort = mxPort = atoi(zPort);
3022 }else{
3023 iPort = db_get_int("http-port", 8080);
3024 mxPort = iPort+100;
3025 }
3026 if( isUiCmd && !fNoBrowser ){
3027 char *zBrowserArg;
 
3028 zBrowser = fossil_web_browser();
3029 if( zIpAddr==0 ){
3030 zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
 
3031 }else if( strchr(zIpAddr,':') ){
3032 zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
 
3033 }else{
3034 zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3035 }
3036 #ifdef _WIN32
3037 zBrowserCmd = mprintf("%s %s &", zBrowser, zBrowserArg);
3038 #else
3039 zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3040 #endif
3041 fossil_free(zBrowserArg);
3042 }
3043 if( zRemote ){
3044 /* If a USER@HOST:REPO argument is supplied, then use SSH to run
3045 ** "fossil ui --nobrowser" on the remote system and to set up a
3046 ** tunnel from the local machine to the remote. */
3047 FILE *sshIn;
3048 Blob ssh;
3049 char zLine[1000];
3050 blob_init(&ssh, 0, 0);
3051 transport_ssh_command(&ssh);
3052 blob_appendf(&ssh,
3053 " -t -L127.0.0.1:%d:127.0.0.1:%d -- %!$"
3054 " fossil ui --nobrowser --localauth --port %d %$",
3055 iPort, iPort, zRemote, iPort, g.argv[2]);
3056 fossil_print("%s\n", blob_str(&ssh));
3057 sshIn = popen(blob_str(&ssh), "r");
3058 if( sshIn==0 ){
3059 fossil_fatal("unable to %s", blob_str(&ssh));
3060 }
3061 while( fgets(zLine, sizeof(zLine), sshIn) ){
3062 fputs(zLine, stdout);
3063 fflush(stdout);
3064 if( zBrowserCmd ){
3065 char *zCmd = mprintf(zBrowserCmd/*works-like:"%d"*/,iPort);
3066 fossil_system(zCmd);
3067 fossil_free(zCmd);
3068 fossil_free(zBrowserCmd);
3069 zBrowserCmd = 0;
3070 }
3071 }
3072 pclose(sshIn);
3073 fossil_free(zBrowserCmd);
3074 return;
3075 }
3076 #if !defined(_WIN32)
3077 /* Unix implementation */
3078 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3079 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3080 db_close(1);
3081 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
3082 fossil_fatal("unable to listen on TCP socket %d", iPort);
@@ -3059,23 +3123,10 @@
3123 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3124 getpid());
3125 }
3126 #else
3127 /* Win32 implementation */
 
 
 
 
 
 
 
 
 
 
 
 
 
3128 if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
3129 if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
3130 db_close(1);
3131 if( allowRepoList ){
3132 flags |= HTTP_SERVER_REPOLIST;
3133
+1 -11
--- src/patch.c
+++ src/patch.c
@@ -19,21 +19,10 @@
1919
*/
2020
#include "config.h"
2121
#include "patch.h"
2222
#include <assert.h>
2323
24
-/*
25
-** Additional windows configuration for popen */
26
-#if defined(_WIN32)
27
-# include <io.h>
28
-# include <fcntl.h>
29
-# undef popen
30
-# define popen _popen
31
-# undef pclose
32
-# define pclose _pclose
33
-#endif
34
-
3524
/*
3625
** Try to compute the name of the computer on which this process
3726
** is running.
3827
*/
3928
char *fossil_hostname(void){
@@ -679,10 +668,11 @@
679668
blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
680669
}else{
681670
Blob remote;
682671
*(char*)(zDir-1) = 0;
683672
transport_ssh_command(&cmd);
673
+ blob_appendf(&cmd, " -T");
684674
blob_append_escaped_arg(&cmd, zRemote, 0);
685675
blob_init(&remote, 0, 0);
686676
blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
687677
zRemoteCmd, zForce, encode64(zDir, -1));
688678
blob_append_escaped_arg(&cmd, blob_str(&remote), 0);
689679
--- src/patch.c
+++ src/patch.c
@@ -19,21 +19,10 @@
19 */
20 #include "config.h"
21 #include "patch.h"
22 #include <assert.h>
23
24 /*
25 ** Additional windows configuration for popen */
26 #if defined(_WIN32)
27 # include <io.h>
28 # include <fcntl.h>
29 # undef popen
30 # define popen _popen
31 # undef pclose
32 # define pclose _pclose
33 #endif
34
35 /*
36 ** Try to compute the name of the computer on which this process
37 ** is running.
38 */
39 char *fossil_hostname(void){
@@ -679,10 +668,11 @@
679 blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
680 }else{
681 Blob remote;
682 *(char*)(zDir-1) = 0;
683 transport_ssh_command(&cmd);
 
684 blob_append_escaped_arg(&cmd, zRemote, 0);
685 blob_init(&remote, 0, 0);
686 blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
687 zRemoteCmd, zForce, encode64(zDir, -1));
688 blob_append_escaped_arg(&cmd, blob_str(&remote), 0);
689
--- src/patch.c
+++ src/patch.c
@@ -19,21 +19,10 @@
19 */
20 #include "config.h"
21 #include "patch.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
 
 
 
 
24 /*
25 ** Try to compute the name of the computer on which this process
26 ** is running.
27 */
28 char *fossil_hostname(void){
@@ -679,10 +668,11 @@
668 blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir);
669 }else{
670 Blob remote;
671 *(char*)(zDir-1) = 0;
672 transport_ssh_command(&cmd);
673 blob_appendf(&cmd, " -T");
674 blob_append_escaped_arg(&cmd, zRemote, 0);
675 blob_init(&remote, 0, 0);
676 blob_appendf(&remote, "fossil patch %s%s --dir64 %z -",
677 zRemoteCmd, zForce, encode64(zDir, -1));
678 blob_append_escaped_arg(&cmd, blob_str(&remote), 0);
679
-9
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112112
assert( nPwdBuffer>0 );
113113
fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114114
}
115115
#endif
116116
117
-#if defined(_WIN32) || defined(WIN32)
118
-# include <io.h>
119
-# include <fcntl.h>
120
-# undef popen
121
-# define popen _popen
122
-# undef pclose
123
-# define pclose _pclose
124
-#endif
125
-
126117
/*
127118
** Scramble substitution matrix:
128119
*/
129120
static char aSubst[256];
130121
131122
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112 assert( nPwdBuffer>0 );
113 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114 }
115 #endif
116
117 #if defined(_WIN32) || defined(WIN32)
118 # include <io.h>
119 # include <fcntl.h>
120 # undef popen
121 # define popen _popen
122 # undef pclose
123 # define pclose _pclose
124 #endif
125
126 /*
127 ** Scramble substitution matrix:
128 */
129 static char aSubst[256];
130
131
--- src/user.c
+++ src/user.c
@@ -112,19 +112,10 @@
112 assert( nPwdBuffer>0 );
113 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
114 }
115 #endif
116
 
 
 
 
 
 
 
 
 
117 /*
118 ** Scramble substitution matrix:
119 */
120 static char aSubst[256];
121
122
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
66
server hostname matches its certificate. <b>Upgrading to
77
the patch is recommended.</b>
88
* The default "ssh" command on Windows is changed to "ssh" instead of the
99
legacy "plink", as ssh is now generally available on Windows systems.
1010
Installations that still need to use the legacy "plink" can make that
11
- happen by running: '<tt>fossil set ssh-command "plink -ssh -T" --global</tt>'.
11
+ happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
1212
* Added the [./patchcmd.md|fossil patch] command.
13
+ * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
14
+ <li> The REPOSITORY argument can be the name of a check-out directory.
15
+ <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
16
+ then the ui is run on the remote machine and tunnelled back to the local
17
+ machine using ssh. (The latest version of fossil must be installed on
18
+ both the local and the remote for this to work correctly.)
19
+ <li> The new --nobrowser option is provided. (This is needed by item 2 above.)
20
+ </ol>
1321
* The [/brlist|/brlist web page] allows the user to
1422
select multiple branches to be displayed together in a single
1523
timeline.
1624
* The [./forum.wiki|Forum] provides a hyperlink on the author of each
1725
post that goes to a timeline of recent posts by that same author.
1826
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
8 * The default "ssh" command on Windows is changed to "ssh" instead of the
9 legacy "plink", as ssh is now generally available on Windows systems.
10 Installations that still need to use the legacy "plink" can make that
11 happen by running: '<tt>fossil set ssh-command "plink -ssh -T" --global</tt>'.
12 * Added the [./patchcmd.md|fossil patch] command.
 
 
 
 
 
 
 
 
13 * The [/brlist|/brlist web page] allows the user to
14 select multiple branches to be displayed together in a single
15 timeline.
16 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
17 post that goes to a timeline of recent posts by that same author.
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
8 * The default "ssh" command on Windows is changed to "ssh" instead of the
9 legacy "plink", as ssh is now generally available on Windows systems.
10 Installations that still need to use the legacy "plink" can make that
11 happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
12 * Added the [./patchcmd.md|fossil patch] command.
13 * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
14 <li> The REPOSITORY argument can be the name of a check-out directory.
15 <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
16 then the ui is run on the remote machine and tunnelled back to the local
17 machine using ssh. (The latest version of fossil must be installed on
18 both the local and the remote for this to work correctly.)
19 <li> The new --nobrowser option is provided. (This is needed by item 2 above.)
20 </ol>
21 * The [/brlist|/brlist web page] allows the user to
22 select multiple branches to be displayed together in a single
23 timeline.
24 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
25 post that goes to a timeline of recent posts by that same author.
26
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
66
server hostname matches its certificate. <b>Upgrading to
77
the patch is recommended.</b>
88
* The default "ssh" command on Windows is changed to "ssh" instead of the
99
legacy "plink", as ssh is now generally available on Windows systems.
1010
Installations that still need to use the legacy "plink" can make that
11
- happen by running: '<tt>fossil set ssh-command "plink -ssh -T" --global</tt>'.
11
+ happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
1212
* Added the [./patchcmd.md|fossil patch] command.
13
+ * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
14
+ <li> The REPOSITORY argument can be the name of a check-out directory.
15
+ <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
16
+ then the ui is run on the remote machine and tunnelled back to the local
17
+ machine using ssh. (The latest version of fossil must be installed on
18
+ both the local and the remote for this to work correctly.)
19
+ <li> The new --nobrowser option is provided. (This is needed by item 2 above.)
20
+ </ol>
1321
* The [/brlist|/brlist web page] allows the user to
1422
select multiple branches to be displayed together in a single
1523
timeline.
1624
* The [./forum.wiki|Forum] provides a hyperlink on the author of each
1725
post that goes to a timeline of recent posts by that same author.
1826
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
8 * The default "ssh" command on Windows is changed to "ssh" instead of the
9 legacy "plink", as ssh is now generally available on Windows systems.
10 Installations that still need to use the legacy "plink" can make that
11 happen by running: '<tt>fossil set ssh-command "plink -ssh -T" --global</tt>'.
12 * Added the [./patchcmd.md|fossil patch] command.
 
 
 
 
 
 
 
 
13 * The [/brlist|/brlist web page] allows the user to
14 select multiple branches to be displayed together in a single
15 timeline.
16 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
17 post that goes to a timeline of recent posts by that same author.
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,12 +6,20 @@
6 server hostname matches its certificate. <b>Upgrading to
7 the patch is recommended.</b>
8 * The default "ssh" command on Windows is changed to "ssh" instead of the
9 legacy "plink", as ssh is now generally available on Windows systems.
10 Installations that still need to use the legacy "plink" can make that
11 happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'.
12 * Added the [./patchcmd.md|fossil patch] command.
13 * The [/help?cmd=ui|fossil ui] command is enhanced in multiple ways:<ol>
14 <li> The REPOSITORY argument can be the name of a check-out directory.
15 <li> If the REPOSITORY argument is prefixed by "HOST:" or "USER@HOST:"
16 then the ui is run on the remote machine and tunnelled back to the local
17 machine using ssh. (The latest version of fossil must be installed on
18 both the local and the remote for this to work correctly.)
19 <li> The new --nobrowser option is provided. (This is needed by item 2 above.)
20 </ol>
21 * The [/brlist|/brlist web page] allows the user to
22 select multiple branches to be displayed together in a single
23 timeline.
24 * The [./forum.wiki|Forum] provides a hyperlink on the author of each
25 post that goes to a timeline of recent posts by that same author.
26

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button