Fossil SCM
Enhance the "fossil ui" command so that the REPOSITORY argument can be on a remote system.
Commit
f3acbe429aa460c82591029efa4f37fb560ba8df58580d7f4e87904572e94eb7
Parent
56a40e3b9d803ae…
11 files changed
-7
+6
-7
-7
+3
-3
+76
-25
+76
-25
+1
-11
-9
+9
-1
+9
-1
-7
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -397,17 +397,10 @@ | ||
| 397 | 397 | iCol += 3; |
| 398 | 398 | } |
| 399 | 399 | } |
| 400 | 400 | } |
| 401 | 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 | 402 | #if INTERFACE |
| 410 | 403 | /* |
| 411 | 404 | ** An instance of the following object is used to send emails. |
| 412 | 405 | */ |
| 413 | 406 | struct AlertSender { |
| 414 | 407 |
| --- 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 |
+6
| --- src/config.h | ||
| +++ src/config.h | ||
| @@ -66,10 +66,16 @@ | ||
| 66 | 66 | typedef int socklen_t; |
| 67 | 67 | # endif |
| 68 | 68 | # ifndef _WIN32 |
| 69 | 69 | # define _WIN32 |
| 70 | 70 | # endif |
| 71 | +# include <io.h> | |
| 72 | +# include <fcntl.h> | |
| 73 | +# undef popen | |
| 74 | +# define popen _popen | |
| 75 | +# undef pclose | |
| 76 | +# define pclose _pclose | |
| 71 | 77 | #else |
| 72 | 78 | # include <sys/types.h> |
| 73 | 79 | # include <signal.h> |
| 74 | 80 | # include <pwd.h> |
| 75 | 81 | #endif |
| 76 | 82 |
| --- 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 |
-7
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -38,17 +38,10 @@ | ||
| 38 | 38 | int rid; /* Corresponding object in the BLOB table */ |
| 39 | 39 | char uuid[65]; /* The GIT hash name for this object */ |
| 40 | 40 | }; |
| 41 | 41 | #endif |
| 42 | 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 | 43 | /* |
| 51 | 44 | ** Output a "committer" record for the given user. |
| 52 | 45 | ** NOTE: the given user name may be an email itself. |
| 53 | 46 | */ |
| 54 | 47 | static void print_person(const char *zUser){ |
| 55 | 48 |
| --- 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 |
-7
| --- src/extcgi.c | ||
| +++ src/extcgi.c | ||
| @@ -30,17 +30,10 @@ | ||
| 30 | 30 | */ |
| 31 | 31 | #include "config.h" |
| 32 | 32 | #include "extcgi.h" |
| 33 | 33 | #include <assert.h> |
| 34 | 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 | 35 | /* |
| 43 | 36 | ** These are the environment variables that should be set for CGI |
| 44 | 37 | ** extension programs: |
| 45 | 38 | */ |
| 46 | 39 | static const char *azCgiEnv[] = { |
| 47 | 40 |
| --- 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 |
+3
-3
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -93,13 +93,13 @@ | ||
| 93 | 93 | |
| 94 | 94 | /* |
| 95 | 95 | ** Default SSH command |
| 96 | 96 | */ |
| 97 | 97 | #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"; | |
| 99 | 99 | #else |
| 100 | -static const char zDefaultSshCmd[] = "ssh -e none -T"; | |
| 100 | +static const char zDefaultSshCmd[] = "ssh -e none"; | |
| 101 | 101 | #endif |
| 102 | 102 | |
| 103 | 103 | /* |
| 104 | 104 | ** Initialize a Blob to the name of the configured SSH command. |
| 105 | 105 | */ |
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | socket_ssh_resolve_addr(pUrlData); |
| 123 | 123 | transport_ssh_command(&zCmd); |
| 124 | 124 | if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ |
| 125 | 125 | blob_appendf(&zCmd, " -p %d", pUrlData->port); |
| 126 | 126 | } |
| 127 | - blob_appendf(&zCmd, " --"); /* End of switches */ | |
| 127 | + blob_appendf(&zCmd, " -T --"); /* End of switches */ | |
| 128 | 128 | if( pUrlData->user && pUrlData->user[0] ){ |
| 129 | 129 | zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); |
| 130 | 130 | blob_append_escaped_arg(&zCmd, zHost, 0); |
| 131 | 131 | fossil_free(zHost); |
| 132 | 132 | }else{ |
| 133 | 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 -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 @@ | ||
| 2816 | 2816 | ** also present. |
| 2817 | 2817 | ** |
| 2818 | 2818 | ** If the REPOSITORY is a directory name which is the root of a |
| 2819 | 2819 | ** checkout, it will chdir to that directory and, unless overridden by |
| 2820 | 2820 | ** 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. | |
| 2822 | 2828 | ** |
| 2823 | -** For the special case REPOSITORY name of "/", the list global configuration | |
| 2829 | +** For the special case REPOSITORY name of "/", the global configuration | |
| 2824 | 2830 | ** database is consulted for a list of all known repositories. The --repolist |
| 2825 | 2831 | ** option is implied by this special case. See also the "fossil all ui" |
| 2826 | 2832 | ** command. |
| 2827 | 2833 | ** |
| 2828 | 2834 | ** By default, the "ui" command provides full administrative access without |
| @@ -2855,10 +2861,12 @@ | ||
| 2855 | 2861 | ** and bundled modes might result in a single |
| 2856 | 2862 | ** amalgamated script or several, but both approaches |
| 2857 | 2863 | ** result in fewer HTTP requests than the separate mode. |
| 2858 | 2864 | ** --max-latency N Do not let any single HTTP request run for more than N |
| 2859 | 2865 | ** seconds (only works on unix) |
| 2866 | +** --nobrowser Do not automatically launch a web-browser for the | |
| 2867 | +** "fossil ui" command. | |
| 2860 | 2868 | ** --nocompress Do not compress HTTP replies |
| 2861 | 2869 | ** --nojail Drop root privileges but do not enter the chroot jail |
| 2862 | 2870 | ** --nossl signal that no SSL connections are available (Always |
| 2863 | 2871 | ** set by default for the "ui" command) |
| 2864 | 2872 | ** --notfound URL Redirect |
| @@ -2890,12 +2898,15 @@ | ||
| 2890 | 2898 | int allowRepoList; /* List repositories on URL "/" */ |
| 2891 | 2899 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2892 | 2900 | const char *zFileGlob; /* Static content must match this */ |
| 2893 | 2901 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2894 | 2902 | int fCreate = 0; /* The --create flag */ |
| 2903 | + int fNoBrowser = 0; /* Do not auto-launch web-browser */ | |
| 2895 | 2904 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2896 | 2905 | int findServerArg = 2; /* argv index for find_server_repository() */ |
| 2906 | + char *zRemote = 0; /* Remote host on which to run "fossil ui" */ | |
| 2907 | + | |
| 2897 | 2908 | |
| 2898 | 2909 | #if defined(_WIN32) |
| 2899 | 2910 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2900 | 2911 | zStopperFile = find_option("stopper", 0, 1); |
| 2901 | 2912 | #endif |
| @@ -2933,10 +2944,11 @@ | ||
| 2933 | 2944 | if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI; |
| 2934 | 2945 | if( zAltBase ){ |
| 2935 | 2946 | set_base_url(zAltBase); |
| 2936 | 2947 | } |
| 2937 | 2948 | g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd; |
| 2949 | + fNoBrowser = find_option("nobrowser", 0, 0)!=0; | |
| 2938 | 2950 | if( find_option("https",0,0)!=0 ){ |
| 2939 | 2951 | cgi_replace_parameter("HTTPS","on"); |
| 2940 | 2952 | } |
| 2941 | 2953 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2942 | 2954 | flags |= HTTP_SERVER_LOCALHOST; |
| @@ -2963,16 +2975,31 @@ | ||
| 2963 | 2975 | fCreate = 0; |
| 2964 | 2976 | g.argv[2] = 0; |
| 2965 | 2977 | --g.argc; |
| 2966 | 2978 | } |
| 2967 | 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 | + } | |
| 2968 | 2993 | if( isUiCmd ){ |
| 2969 | 2994 | flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST; |
| 2970 | 2995 | g.useLocalauth = 1; |
| 2971 | 2996 | allowRepoList = 1; |
| 2972 | 2997 | } |
| 2973 | - find_server_repository(findServerArg, fCreate); | |
| 2998 | + if( !zRemote ){ | |
| 2999 | + find_server_repository(findServerArg, fCreate); | |
| 3000 | + } | |
| 2974 | 3001 | if( zInitPage==0 ){ |
| 2975 | 3002 | if( isUiCmd && g.localOpen ){ |
| 2976 | 3003 | zInitPage = "timeline?c=current"; |
| 2977 | 3004 | }else{ |
| 2978 | 3005 | zInitPage = ""; |
| @@ -2994,25 +3021,62 @@ | ||
| 2994 | 3021 | iPort = mxPort = atoi(zPort); |
| 2995 | 3022 | }else{ |
| 2996 | 3023 | iPort = db_get_int("http-port", 8080); |
| 2997 | 3024 | mxPort = iPort+100; |
| 2998 | 3025 | } |
| 2999 | -#if !defined(_WIN32) | |
| 3000 | - /* Unix implementation */ | |
| 3001 | - if( isUiCmd ){ | |
| 3026 | + if( isUiCmd && !fNoBrowser ){ | |
| 3027 | + char *zBrowserArg; | |
| 3002 | 3028 | zBrowser = fossil_web_browser(); |
| 3003 | 3029 | if( zIpAddr==0 ){ |
| 3004 | - zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &", | |
| 3005 | - zBrowser, zInitPage); | |
| 3030 | + zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage); | |
| 3006 | 3031 | }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); | |
| 3009 | 3033 | }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 | + } | |
| 3012 | 3071 | } |
| 3072 | + pclose(sshIn); | |
| 3073 | + fossil_free(zBrowserCmd); | |
| 3074 | + return; | |
| 3013 | 3075 | } |
| 3076 | +#if !defined(_WIN32) | |
| 3077 | + /* Unix implementation */ | |
| 3014 | 3078 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3015 | 3079 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3016 | 3080 | db_close(1); |
| 3017 | 3081 | if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ |
| 3018 | 3082 | fossil_fatal("unable to listen on TCP socket %d", iPort); |
| @@ -3059,23 +3123,10 @@ | ||
| 3059 | 3123 | fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n", |
| 3060 | 3124 | getpid()); |
| 3061 | 3125 | } |
| 3062 | 3126 | #else |
| 3063 | 3127 | /* 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 | 3128 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3078 | 3129 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3079 | 3130 | db_close(1); |
| 3080 | 3131 | if( allowRepoList ){ |
| 3081 | 3132 | flags |= HTTP_SERVER_REPOLIST; |
| 3082 | 3133 |
| --- 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 @@ | ||
| 2816 | 2816 | ** also present. |
| 2817 | 2817 | ** |
| 2818 | 2818 | ** If the REPOSITORY is a directory name which is the root of a |
| 2819 | 2819 | ** checkout, it will chdir to that directory and, unless overridden by |
| 2820 | 2820 | ** 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. | |
| 2822 | 2828 | ** |
| 2823 | -** For the special case REPOSITORY name of "/", the list global configuration | |
| 2829 | +** For the special case REPOSITORY name of "/", the global configuration | |
| 2824 | 2830 | ** database is consulted for a list of all known repositories. The --repolist |
| 2825 | 2831 | ** option is implied by this special case. See also the "fossil all ui" |
| 2826 | 2832 | ** command. |
| 2827 | 2833 | ** |
| 2828 | 2834 | ** By default, the "ui" command provides full administrative access without |
| @@ -2855,10 +2861,12 @@ | ||
| 2855 | 2861 | ** and bundled modes might result in a single |
| 2856 | 2862 | ** amalgamated script or several, but both approaches |
| 2857 | 2863 | ** result in fewer HTTP requests than the separate mode. |
| 2858 | 2864 | ** --max-latency N Do not let any single HTTP request run for more than N |
| 2859 | 2865 | ** seconds (only works on unix) |
| 2866 | +** --nobrowser Do not automatically launch a web-browser for the | |
| 2867 | +** "fossil ui" command. | |
| 2860 | 2868 | ** --nocompress Do not compress HTTP replies |
| 2861 | 2869 | ** --nojail Drop root privileges but do not enter the chroot jail |
| 2862 | 2870 | ** --nossl signal that no SSL connections are available (Always |
| 2863 | 2871 | ** set by default for the "ui" command) |
| 2864 | 2872 | ** --notfound URL Redirect |
| @@ -2890,12 +2898,15 @@ | ||
| 2890 | 2898 | int allowRepoList; /* List repositories on URL "/" */ |
| 2891 | 2899 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 2892 | 2900 | const char *zFileGlob; /* Static content must match this */ |
| 2893 | 2901 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 2894 | 2902 | int fCreate = 0; /* The --create flag */ |
| 2903 | + int fNoBrowser = 0; /* Do not auto-launch web-browser */ | |
| 2895 | 2904 | const char *zInitPage = 0; /* Start on this page. --page option */ |
| 2896 | 2905 | int findServerArg = 2; /* argv index for find_server_repository() */ |
| 2906 | + char *zRemote = 0; /* Remote host on which to run "fossil ui" */ | |
| 2907 | + | |
| 2897 | 2908 | |
| 2898 | 2909 | #if defined(_WIN32) |
| 2899 | 2910 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 2900 | 2911 | zStopperFile = find_option("stopper", 0, 1); |
| 2901 | 2912 | #endif |
| @@ -2933,10 +2944,11 @@ | ||
| 2933 | 2944 | if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI; |
| 2934 | 2945 | if( zAltBase ){ |
| 2935 | 2946 | set_base_url(zAltBase); |
| 2936 | 2947 | } |
| 2937 | 2948 | g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd; |
| 2949 | + fNoBrowser = find_option("nobrowser", 0, 0)!=0; | |
| 2938 | 2950 | if( find_option("https",0,0)!=0 ){ |
| 2939 | 2951 | cgi_replace_parameter("HTTPS","on"); |
| 2940 | 2952 | } |
| 2941 | 2953 | if( find_option("localhost", 0, 0)!=0 ){ |
| 2942 | 2954 | flags |= HTTP_SERVER_LOCALHOST; |
| @@ -2963,16 +2975,31 @@ | ||
| 2963 | 2975 | fCreate = 0; |
| 2964 | 2976 | g.argv[2] = 0; |
| 2965 | 2977 | --g.argc; |
| 2966 | 2978 | } |
| 2967 | 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 | + } | |
| 2968 | 2993 | if( isUiCmd ){ |
| 2969 | 2994 | flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST; |
| 2970 | 2995 | g.useLocalauth = 1; |
| 2971 | 2996 | allowRepoList = 1; |
| 2972 | 2997 | } |
| 2973 | - find_server_repository(findServerArg, fCreate); | |
| 2998 | + if( !zRemote ){ | |
| 2999 | + find_server_repository(findServerArg, fCreate); | |
| 3000 | + } | |
| 2974 | 3001 | if( zInitPage==0 ){ |
| 2975 | 3002 | if( isUiCmd && g.localOpen ){ |
| 2976 | 3003 | zInitPage = "timeline?c=current"; |
| 2977 | 3004 | }else{ |
| 2978 | 3005 | zInitPage = ""; |
| @@ -2994,25 +3021,62 @@ | ||
| 2994 | 3021 | iPort = mxPort = atoi(zPort); |
| 2995 | 3022 | }else{ |
| 2996 | 3023 | iPort = db_get_int("http-port", 8080); |
| 2997 | 3024 | mxPort = iPort+100; |
| 2998 | 3025 | } |
| 2999 | -#if !defined(_WIN32) | |
| 3000 | - /* Unix implementation */ | |
| 3001 | - if( isUiCmd ){ | |
| 3026 | + if( isUiCmd && !fNoBrowser ){ | |
| 3027 | + char *zBrowserArg; | |
| 3002 | 3028 | zBrowser = fossil_web_browser(); |
| 3003 | 3029 | if( zIpAddr==0 ){ |
| 3004 | - zBrowserCmd = mprintf("%s \"http://localhost:%%d/%s\" &", | |
| 3005 | - zBrowser, zInitPage); | |
| 3030 | + zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage); | |
| 3006 | 3031 | }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); | |
| 3009 | 3033 | }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 | + } | |
| 3012 | 3071 | } |
| 3072 | + pclose(sshIn); | |
| 3073 | + fossil_free(zBrowserCmd); | |
| 3074 | + return; | |
| 3013 | 3075 | } |
| 3076 | +#if !defined(_WIN32) | |
| 3077 | + /* Unix implementation */ | |
| 3014 | 3078 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3015 | 3079 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3016 | 3080 | db_close(1); |
| 3017 | 3081 | if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ |
| 3018 | 3082 | fossil_fatal("unable to listen on TCP socket %d", iPort); |
| @@ -3059,23 +3123,10 @@ | ||
| 3059 | 3123 | fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n", |
| 3060 | 3124 | getpid()); |
| 3061 | 3125 | } |
| 3062 | 3126 | #else |
| 3063 | 3127 | /* 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 | 3128 | if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY; |
| 3078 | 3129 | if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT; |
| 3079 | 3130 | db_close(1); |
| 3080 | 3131 | if( allowRepoList ){ |
| 3081 | 3132 | flags |= HTTP_SERVER_REPOLIST; |
| 3082 | 3133 |
| --- 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 @@ | ||
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include "patch.h" |
| 22 | 22 | #include <assert.h> |
| 23 | 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 | 24 | /* |
| 36 | 25 | ** Try to compute the name of the computer on which this process |
| 37 | 26 | ** is running. |
| 38 | 27 | */ |
| 39 | 28 | char *fossil_hostname(void){ |
| @@ -679,10 +668,11 @@ | ||
| 679 | 668 | blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir); |
| 680 | 669 | }else{ |
| 681 | 670 | Blob remote; |
| 682 | 671 | *(char*)(zDir-1) = 0; |
| 683 | 672 | transport_ssh_command(&cmd); |
| 673 | + blob_appendf(&cmd, " -T"); | |
| 684 | 674 | blob_append_escaped_arg(&cmd, zRemote, 0); |
| 685 | 675 | blob_init(&remote, 0, 0); |
| 686 | 676 | blob_appendf(&remote, "fossil patch %s%s --dir64 %z -", |
| 687 | 677 | zRemoteCmd, zForce, encode64(zDir, -1)); |
| 688 | 678 | blob_append_escaped_arg(&cmd, blob_str(&remote), 0); |
| 689 | 679 |
| --- 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 @@ | ||
| 112 | 112 | assert( nPwdBuffer>0 ); |
| 113 | 113 | fossil_secure_free_page(zPwdBuffer, nPwdBuffer); |
| 114 | 114 | } |
| 115 | 115 | #endif |
| 116 | 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 | 117 | /* |
| 127 | 118 | ** Scramble substitution matrix: |
| 128 | 119 | */ |
| 129 | 120 | static char aSubst[256]; |
| 130 | 121 | |
| 131 | 122 |
| --- 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 |
+9
-1
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -6,12 +6,20 @@ | ||
| 6 | 6 | server hostname matches its certificate. <b>Upgrading to |
| 7 | 7 | the patch is recommended.</b> |
| 8 | 8 | * The default "ssh" command on Windows is changed to "ssh" instead of the |
| 9 | 9 | legacy "plink", as ssh is now generally available on Windows systems. |
| 10 | 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>'. | |
| 11 | + happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'. | |
| 12 | 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> | |
| 13 | 21 | * The [/brlist|/brlist web page] allows the user to |
| 14 | 22 | select multiple branches to be displayed together in a single |
| 15 | 23 | timeline. |
| 16 | 24 | * The [./forum.wiki|Forum] provides a hyperlink on the author of each |
| 17 | 25 | post that goes to a timeline of recent posts by that same author. |
| 18 | 26 |
| --- 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 |
+9
-1
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -6,12 +6,20 @@ | ||
| 6 | 6 | server hostname matches its certificate. <b>Upgrading to |
| 7 | 7 | the patch is recommended.</b> |
| 8 | 8 | * The default "ssh" command on Windows is changed to "ssh" instead of the |
| 9 | 9 | legacy "plink", as ssh is now generally available on Windows systems. |
| 10 | 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>'. | |
| 11 | + happen by running: '<tt>fossil set ssh-command "plink -ssh" --global</tt>'. | |
| 12 | 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> | |
| 13 | 21 | * The [/brlist|/brlist web page] allows the user to |
| 14 | 22 | select multiple branches to be displayed together in a single |
| 15 | 23 | timeline. |
| 16 | 24 | * The [./forum.wiki|Forum] provides a hyperlink on the author of each |
| 17 | 25 | post that goes to a timeline of recent posts by that same author. |
| 18 | 26 |
| --- 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 |