Fossil SCM
Changes that allow the --port option on "fossil ui" and "fossil server" to include an IP address to which to bind.
Commit
abf56881b696f60fbff42d6567ea6f12a4723b59
Parent
12ff5ff85e0b61f…
3 files changed
+12
-2
+14
-3
+9
-2
+12
-2
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1272,11 +1272,16 @@ | ||
| 1272 | 1272 | ** The parent never returns from this procedure. |
| 1273 | 1273 | ** |
| 1274 | 1274 | ** Return 0 to each child as it runs. If unable to establish a |
| 1275 | 1275 | ** listening socket, return non-zero. |
| 1276 | 1276 | */ |
| 1277 | -int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){ | |
| 1277 | +int cgi_http_server( | |
| 1278 | + int mnPort, int mxPort, /* Range of TCP ports to try */ | |
| 1279 | + const char *zBrowser, /* Run this browser, if not NULL */ | |
| 1280 | + const char *zIpAddr, /* Bind to this IP address, if not null */ | |
| 1281 | + int flags /* HTTP_SERVER_* flags */ | |
| 1282 | +){ | |
| 1278 | 1283 | #if defined(_WIN32) |
| 1279 | 1284 | /* Use win32_http_server() instead */ |
| 1280 | 1285 | fossil_exit(1); |
| 1281 | 1286 | #else |
| 1282 | 1287 | int listener = -1; /* The server socket */ |
| @@ -1291,11 +1296,16 @@ | ||
| 1291 | 1296 | int iPort = mnPort; |
| 1292 | 1297 | |
| 1293 | 1298 | while( iPort<=mxPort ){ |
| 1294 | 1299 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1295 | 1300 | inaddr.sin_family = AF_INET; |
| 1296 | - if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 1301 | + if( zIpAddr ){ | |
| 1302 | + inaddr.sin_addr.s_addr = inet_addr(zIpAddr); | |
| 1303 | + if( inaddr.sin_addr.s_addr == (-1) ){ | |
| 1304 | + fossil_fatal("not a valid IP address: %s", zIpAddr); | |
| 1305 | + } | |
| 1306 | + }else if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 1297 | 1307 | inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 1298 | 1308 | }else{ |
| 1299 | 1309 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 1300 | 1310 | } |
| 1301 | 1311 | inaddr.sin_port = htons(iPort); |
| 1302 | 1312 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1272,11 +1272,16 @@ | |
| 1272 | ** The parent never returns from this procedure. |
| 1273 | ** |
| 1274 | ** Return 0 to each child as it runs. If unable to establish a |
| 1275 | ** listening socket, return non-zero. |
| 1276 | */ |
| 1277 | int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){ |
| 1278 | #if defined(_WIN32) |
| 1279 | /* Use win32_http_server() instead */ |
| 1280 | fossil_exit(1); |
| 1281 | #else |
| 1282 | int listener = -1; /* The server socket */ |
| @@ -1291,11 +1296,16 @@ | |
| 1291 | int iPort = mnPort; |
| 1292 | |
| 1293 | while( iPort<=mxPort ){ |
| 1294 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1295 | inaddr.sin_family = AF_INET; |
| 1296 | if( flags & HTTP_SERVER_LOCALHOST ){ |
| 1297 | inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 1298 | }else{ |
| 1299 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 1300 | } |
| 1301 | inaddr.sin_port = htons(iPort); |
| 1302 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1272,11 +1272,16 @@ | |
| 1272 | ** The parent never returns from this procedure. |
| 1273 | ** |
| 1274 | ** Return 0 to each child as it runs. If unable to establish a |
| 1275 | ** listening socket, return non-zero. |
| 1276 | */ |
| 1277 | int cgi_http_server( |
| 1278 | int mnPort, int mxPort, /* Range of TCP ports to try */ |
| 1279 | const char *zBrowser, /* Run this browser, if not NULL */ |
| 1280 | const char *zIpAddr, /* Bind to this IP address, if not null */ |
| 1281 | int flags /* HTTP_SERVER_* flags */ |
| 1282 | ){ |
| 1283 | #if defined(_WIN32) |
| 1284 | /* Use win32_http_server() instead */ |
| 1285 | fossil_exit(1); |
| 1286 | #else |
| 1287 | int listener = -1; /* The server socket */ |
| @@ -1291,11 +1296,16 @@ | |
| 1296 | int iPort = mnPort; |
| 1297 | |
| 1298 | while( iPort<=mxPort ){ |
| 1299 | memset(&inaddr, 0, sizeof(inaddr)); |
| 1300 | inaddr.sin_family = AF_INET; |
| 1301 | if( zIpAddr ){ |
| 1302 | inaddr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 1303 | if( inaddr.sin_addr.s_addr == (-1) ){ |
| 1304 | fossil_fatal("not a valid IP address: %s", zIpAddr); |
| 1305 | } |
| 1306 | }else if( flags & HTTP_SERVER_LOCALHOST ){ |
| 1307 | inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 1308 | }else{ |
| 1309 | inaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 1310 | } |
| 1311 | inaddr.sin_port = htons(iPort); |
| 1312 |
+14
-3
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1890,10 +1890,11 @@ | ||
| 1890 | 1890 | int isUiCmd; /* True if command is "ui", not "server' */ |
| 1891 | 1891 | const char *zNotFound; /* The --notfound option or NULL */ |
| 1892 | 1892 | int flags = 0; /* Server flags */ |
| 1893 | 1893 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 1894 | 1894 | const char *zFileGlob; /* Static content must match this */ |
| 1895 | + char *zIpAddr = 0; /* Bind to this IP address */ | |
| 1895 | 1896 | |
| 1896 | 1897 | #if defined(_WIN32) |
| 1897 | 1898 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 1898 | 1899 | zStopperFile = find_option("stopper", 0, 1); |
| 1899 | 1900 | #endif |
| @@ -1916,10 +1917,16 @@ | ||
| 1916 | 1917 | flags |= HTTP_SERVER_LOCALHOST; |
| 1917 | 1918 | g.useLocalauth = 1; |
| 1918 | 1919 | } |
| 1919 | 1920 | find_server_repository(isUiCmd && zNotFound==0); |
| 1920 | 1921 | if( zPort ){ |
| 1922 | + int i; | |
| 1923 | + for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){} | |
| 1924 | + if( i>0 ){ | |
| 1925 | + zIpAddr = mprintf("%.*s", i, zPort); | |
| 1926 | + zPort += i+1; | |
| 1927 | + } | |
| 1921 | 1928 | iPort = mxPort = atoi(zPort); |
| 1922 | 1929 | }else{ |
| 1923 | 1930 | iPort = db_get_int("http-port", 8080); |
| 1924 | 1931 | mxPort = iPort+100; |
| 1925 | 1932 | } |
| @@ -1941,14 +1948,18 @@ | ||
| 1941 | 1948 | } |
| 1942 | 1949 | } |
| 1943 | 1950 | #else |
| 1944 | 1951 | zBrowser = db_get("web-browser", "open"); |
| 1945 | 1952 | #endif |
| 1946 | - zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); | |
| 1953 | + if( zIpAddr ){ | |
| 1954 | + zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr); | |
| 1955 | + }else{ | |
| 1956 | + zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); | |
| 1957 | + } | |
| 1947 | 1958 | } |
| 1948 | 1959 | db_close(1); |
| 1949 | - if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){ | |
| 1960 | + if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ | |
| 1950 | 1961 | fossil_fatal("unable to listen on TCP socket %d", iPort); |
| 1951 | 1962 | } |
| 1952 | 1963 | g.sslNotAvailable = 1; |
| 1953 | 1964 | g.httpIn = stdin; |
| 1954 | 1965 | g.httpOut = stdout; |
| @@ -1965,11 +1976,11 @@ | ||
| 1965 | 1976 | if( isUiCmd ){ |
| 1966 | 1977 | zBrowser = db_get("web-browser", "start"); |
| 1967 | 1978 | zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser); |
| 1968 | 1979 | } |
| 1969 | 1980 | db_close(1); |
| 1970 | - if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){ | |
| 1981 | + if( win32_http_service(iPort, zNotFound, zFileGlob, zIpAddr, flags) ){ | |
| 1971 | 1982 | win32_http_server(iPort, mxPort, zBrowserCmd, |
| 1972 | 1983 | zStopperFile, zNotFound, zFileGlob, flags); |
| 1973 | 1984 | } |
| 1974 | 1985 | #endif |
| 1975 | 1986 | } |
| 1976 | 1987 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1890,10 +1890,11 @@ | |
| 1890 | int isUiCmd; /* True if command is "ui", not "server' */ |
| 1891 | const char *zNotFound; /* The --notfound option or NULL */ |
| 1892 | int flags = 0; /* Server flags */ |
| 1893 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 1894 | const char *zFileGlob; /* Static content must match this */ |
| 1895 | |
| 1896 | #if defined(_WIN32) |
| 1897 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 1898 | zStopperFile = find_option("stopper", 0, 1); |
| 1899 | #endif |
| @@ -1916,10 +1917,16 @@ | |
| 1916 | flags |= HTTP_SERVER_LOCALHOST; |
| 1917 | g.useLocalauth = 1; |
| 1918 | } |
| 1919 | find_server_repository(isUiCmd && zNotFound==0); |
| 1920 | if( zPort ){ |
| 1921 | iPort = mxPort = atoi(zPort); |
| 1922 | }else{ |
| 1923 | iPort = db_get_int("http-port", 8080); |
| 1924 | mxPort = iPort+100; |
| 1925 | } |
| @@ -1941,14 +1948,18 @@ | |
| 1941 | } |
| 1942 | } |
| 1943 | #else |
| 1944 | zBrowser = db_get("web-browser", "open"); |
| 1945 | #endif |
| 1946 | zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); |
| 1947 | } |
| 1948 | db_close(1); |
| 1949 | if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){ |
| 1950 | fossil_fatal("unable to listen on TCP socket %d", iPort); |
| 1951 | } |
| 1952 | g.sslNotAvailable = 1; |
| 1953 | g.httpIn = stdin; |
| 1954 | g.httpOut = stdout; |
| @@ -1965,11 +1976,11 @@ | |
| 1965 | if( isUiCmd ){ |
| 1966 | zBrowser = db_get("web-browser", "start"); |
| 1967 | zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser); |
| 1968 | } |
| 1969 | db_close(1); |
| 1970 | if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){ |
| 1971 | win32_http_server(iPort, mxPort, zBrowserCmd, |
| 1972 | zStopperFile, zNotFound, zFileGlob, flags); |
| 1973 | } |
| 1974 | #endif |
| 1975 | } |
| 1976 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1890,10 +1890,11 @@ | |
| 1890 | int isUiCmd; /* True if command is "ui", not "server' */ |
| 1891 | const char *zNotFound; /* The --notfound option or NULL */ |
| 1892 | int flags = 0; /* Server flags */ |
| 1893 | const char *zAltBase; /* Argument to the --baseurl option */ |
| 1894 | const char *zFileGlob; /* Static content must match this */ |
| 1895 | char *zIpAddr = 0; /* Bind to this IP address */ |
| 1896 | |
| 1897 | #if defined(_WIN32) |
| 1898 | const char *zStopperFile; /* Name of file used to terminate server */ |
| 1899 | zStopperFile = find_option("stopper", 0, 1); |
| 1900 | #endif |
| @@ -1916,10 +1917,16 @@ | |
| 1917 | flags |= HTTP_SERVER_LOCALHOST; |
| 1918 | g.useLocalauth = 1; |
| 1919 | } |
| 1920 | find_server_repository(isUiCmd && zNotFound==0); |
| 1921 | if( zPort ){ |
| 1922 | int i; |
| 1923 | for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){} |
| 1924 | if( i>0 ){ |
| 1925 | zIpAddr = mprintf("%.*s", i, zPort); |
| 1926 | zPort += i+1; |
| 1927 | } |
| 1928 | iPort = mxPort = atoi(zPort); |
| 1929 | }else{ |
| 1930 | iPort = db_get_int("http-port", 8080); |
| 1931 | mxPort = iPort+100; |
| 1932 | } |
| @@ -1941,14 +1948,18 @@ | |
| 1948 | } |
| 1949 | } |
| 1950 | #else |
| 1951 | zBrowser = db_get("web-browser", "open"); |
| 1952 | #endif |
| 1953 | if( zIpAddr ){ |
| 1954 | zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr); |
| 1955 | }else{ |
| 1956 | zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser); |
| 1957 | } |
| 1958 | } |
| 1959 | db_close(1); |
| 1960 | if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){ |
| 1961 | fossil_fatal("unable to listen on TCP socket %d", iPort); |
| 1962 | } |
| 1963 | g.sslNotAvailable = 1; |
| 1964 | g.httpIn = stdin; |
| 1965 | g.httpOut = stdout; |
| @@ -1965,11 +1976,11 @@ | |
| 1976 | if( isUiCmd ){ |
| 1977 | zBrowser = db_get("web-browser", "start"); |
| 1978 | zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser); |
| 1979 | } |
| 1980 | db_close(1); |
| 1981 | if( win32_http_service(iPort, zNotFound, zFileGlob, zIpAddr, flags) ){ |
| 1982 | win32_http_server(iPort, mxPort, zBrowserCmd, |
| 1983 | zStopperFile, zNotFound, zFileGlob, flags); |
| 1984 | } |
| 1985 | #endif |
| 1986 | } |
| 1987 |
+9
-2
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -139,10 +139,11 @@ | ||
| 139 | 139 | int mnPort, int mxPort, /* Range of allowed TCP port numbers */ |
| 140 | 140 | const char *zBrowser, /* Command to launch browser. (Or NULL) */ |
| 141 | 141 | const char *zStopper, /* Stop server when this file is exists (Or NULL) */ |
| 142 | 142 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 143 | 143 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 144 | + const char *zIpAddr, /* Bind to this IP address, if not NULL */ | |
| 144 | 145 | int flags /* One or more HTTP_SERVER_ flags */ |
| 145 | 146 | ){ |
| 146 | 147 | WSADATA wd; |
| 147 | 148 | SOCKET s = INVALID_SOCKET; |
| 148 | 149 | SOCKADDR_IN addr; |
| @@ -170,11 +171,16 @@ | ||
| 170 | 171 | if( s==INVALID_SOCKET ){ |
| 171 | 172 | fossil_fatal("unable to create a socket"); |
| 172 | 173 | } |
| 173 | 174 | addr.sin_family = AF_INET; |
| 174 | 175 | addr.sin_port = htons(iPort); |
| 175 | - if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 176 | + if( zIpAddr ){ | |
| 177 | + addr.sin_addr.s_addr = inet_addr(zIpAddr); | |
| 178 | + if( addr.sin_addr.s_addr == (-1) ){ | |
| 179 | + fossil_fatal("not a valid IP address: %s", zIpAddr); | |
| 180 | + } | |
| 181 | + }else if( flags & HTTP_SERVER_LOCALHOST ){ | |
| 176 | 182 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 177 | 183 | }else{ |
| 178 | 184 | addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 179 | 185 | } |
| 180 | 186 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| @@ -198,11 +204,12 @@ | ||
| 198 | 204 | } |
| 199 | 205 | } |
| 200 | 206 | if( !GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 201 | 207 | fossil_fatal("unable to get path to the temporary directory."); |
| 202 | 208 | } |
| 203 | - zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); | |
| 209 | + zTempPrefix = mprintf("%sfossil_server_P%d_", | |
| 210 | + fossil_unicode_to_utf8(zTmpPath), iPort); | |
| 204 | 211 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 205 | 212 | if( zBrowser ){ |
| 206 | 213 | zBrowser = mprintf(zBrowser, iPort); |
| 207 | 214 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 208 | 215 | fossil_system(zBrowser); |
| 209 | 216 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -139,10 +139,11 @@ | |
| 139 | int mnPort, int mxPort, /* Range of allowed TCP port numbers */ |
| 140 | const char *zBrowser, /* Command to launch browser. (Or NULL) */ |
| 141 | const char *zStopper, /* Stop server when this file is exists (Or NULL) */ |
| 142 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 143 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 144 | int flags /* One or more HTTP_SERVER_ flags */ |
| 145 | ){ |
| 146 | WSADATA wd; |
| 147 | SOCKET s = INVALID_SOCKET; |
| 148 | SOCKADDR_IN addr; |
| @@ -170,11 +171,16 @@ | |
| 170 | if( s==INVALID_SOCKET ){ |
| 171 | fossil_fatal("unable to create a socket"); |
| 172 | } |
| 173 | addr.sin_family = AF_INET; |
| 174 | addr.sin_port = htons(iPort); |
| 175 | if( flags & HTTP_SERVER_LOCALHOST ){ |
| 176 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 177 | }else{ |
| 178 | addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 179 | } |
| 180 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| @@ -198,11 +204,12 @@ | |
| 198 | } |
| 199 | } |
| 200 | if( !GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 201 | fossil_fatal("unable to get path to the temporary directory."); |
| 202 | } |
| 203 | zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); |
| 204 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 205 | if( zBrowser ){ |
| 206 | zBrowser = mprintf(zBrowser, iPort); |
| 207 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 208 | fossil_system(zBrowser); |
| 209 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -139,10 +139,11 @@ | |
| 139 | int mnPort, int mxPort, /* Range of allowed TCP port numbers */ |
| 140 | const char *zBrowser, /* Command to launch browser. (Or NULL) */ |
| 141 | const char *zStopper, /* Stop server when this file is exists (Or NULL) */ |
| 142 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 143 | const char *zFileGlob, /* The --fileglob option, or NULL */ |
| 144 | const char *zIpAddr, /* Bind to this IP address, if not NULL */ |
| 145 | int flags /* One or more HTTP_SERVER_ flags */ |
| 146 | ){ |
| 147 | WSADATA wd; |
| 148 | SOCKET s = INVALID_SOCKET; |
| 149 | SOCKADDR_IN addr; |
| @@ -170,11 +171,16 @@ | |
| 171 | if( s==INVALID_SOCKET ){ |
| 172 | fossil_fatal("unable to create a socket"); |
| 173 | } |
| 174 | addr.sin_family = AF_INET; |
| 175 | addr.sin_port = htons(iPort); |
| 176 | if( zIpAddr ){ |
| 177 | addr.sin_addr.s_addr = inet_addr(zIpAddr); |
| 178 | if( addr.sin_addr.s_addr == (-1) ){ |
| 179 | fossil_fatal("not a valid IP address: %s", zIpAddr); |
| 180 | } |
| 181 | }else if( flags & HTTP_SERVER_LOCALHOST ){ |
| 182 | addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 183 | }else{ |
| 184 | addr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 185 | } |
| 186 | if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){ |
| @@ -198,11 +204,12 @@ | |
| 204 | } |
| 205 | } |
| 206 | if( !GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 207 | fossil_fatal("unable to get path to the temporary directory."); |
| 208 | } |
| 209 | zTempPrefix = mprintf("%sfossil_server_P%d_", |
| 210 | fossil_unicode_to_utf8(zTmpPath), iPort); |
| 211 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 212 | if( zBrowser ){ |
| 213 | zBrowser = mprintf(zBrowser, iPort); |
| 214 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 215 | fossil_system(zBrowser); |
| 216 |