Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge the ssh:// sync enhancement into the trunk. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
0e42cc1b77f07d00546d001f3052201c |
| User & Date: | drh 2010-08-25 20:00:40.000 |
Context
|
2010-08-26
| ||
| 11:31 | Enable proxy handling for "config push" and "config pull" Tickets [0d1a4fe14f1fb6ee2082] and [311fbfd6b696142a4b2c86dc]. check-in: 1a9fe88b66 user: drh tags: trunk | |
|
2010-08-25
| ||
| 20:00 | Merge the ssh:// sync enhancement into the trunk. check-in: 0e42cc1b77 user: drh tags: trunk | |
| 19:55 | Change the "ui" and "sshd" commands so that they bind to INADDR_LOOPBACK rather than INADDR_ANY. Disable the "quit" monitoring on "ui" and "server". Add better error messages explaining that ssh:// is not yet supported on windows. check-in: 2f8e4c4b38 user: drh tags: experimental | |
|
2010-08-24
| ||
| 01:24 | Fix a potential sigfault that can occur in the graph generator if the child is older than its parent. check-in: 7503f98779 user: drh tags: trunk | |
Changes
Changes to src/cgi.c.
| ︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 |
cgi_set_status(501, "Not Implemented");
cgi_printf(
"<html><body>Unrecognized HTTP Request</body></html>\n"
);
cgi_reply();
fossil_exit(0);
}
/*
** Panic and die while processing a webpage.
*/
void cgi_panic(const char *zFormat, ...){
va_list ap;
cgi_reset_content();
| > > > > > > > > > > > > | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
cgi_set_status(501, "Not Implemented");
cgi_printf(
"<html><body>Unrecognized HTTP Request</body></html>\n"
);
cgi_reply();
fossil_exit(0);
}
/*
** Send a reply indicating that the HTTP request is forbidden
*/
static void forbidden_request(void){
cgi_set_status(403, "Forbidden");
cgi_printf(
"<html><body>Access Denied</body></html>\n"
);
cgi_reply();
fossil_exit(0);
}
/*
** Panic and die while processing a webpage.
*/
void cgi_panic(const char *zFormat, ...){
va_list ap;
cgi_reset_content();
|
| ︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 |
** and subsequent code handles the actual generation of the webpage.
*/
void cgi_handle_http_request(const char *zIpAddr){
char *z, *zToken;
int i;
struct sockaddr_in remoteName;
size_t size = sizeof(struct sockaddr_in);
char zLine[2000]; /* A single line of input. */
g.fullHttpReply = 1;
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
malformed_request();
}
zToken = extract_token(zLine, &z);
| > | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 |
** and subsequent code handles the actual generation of the webpage.
*/
void cgi_handle_http_request(const char *zIpAddr){
char *z, *zToken;
int i;
struct sockaddr_in remoteName;
size_t size = sizeof(struct sockaddr_in);
int accessTokenSeen = 0;
char zLine[2000]; /* A single line of input. */
g.fullHttpReply = 1;
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
malformed_request();
}
zToken = extract_token(zLine, &z);
|
| ︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 |
zFieldName = extract_token(zLine,&zVal);
if( zFieldName==0 || *zFieldName==0 ) break;
while( isspace(*zVal) ){ zVal++; }
i = strlen(zVal);
while( i>0 && isspace(zVal[i-1]) ){ i--; }
zVal[i] = 0;
for(i=0; zFieldName[i]; i++){ zFieldName[i] = tolower(zFieldName[i]); }
| < < | < < < < > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > | > > > | > | 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 |
zFieldName = extract_token(zLine,&zVal);
if( zFieldName==0 || *zFieldName==0 ) break;
while( isspace(*zVal) ){ zVal++; }
i = strlen(zVal);
while( i>0 && isspace(zVal[i-1]) ){ i--; }
zVal[i] = 0;
for(i=0; zFieldName[i]; i++){ zFieldName[i] = tolower(zFieldName[i]); }
if( strcmp(zFieldName,"content-length:")==0 ){
cgi_setenv("CONTENT_LENGTH", zVal);
}else if( strcmp(zFieldName,"content-type:")==0 ){
cgi_setenv("CONTENT_TYPE", zVal);
}else if( strcmp(zFieldName,"cookie:")==0 ){
cgi_setenv("HTTP_COOKIE", zVal);
}else if( strcmp(zFieldName,"https:")==0 ){
cgi_setenv("HTTPS", zVal);
}else if( strcmp(zFieldName,"host:")==0 ){
cgi_setenv("HTTP_HOST", zVal);
}else if( strcmp(zFieldName,"if-none-match:")==0 ){
cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
}else if( strcmp(zFieldName,"if-modified-since:")==0 ){
cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
}else if( strcmp(zFieldName,"x-fossil-access-token:")==0 ){
if( g.zAccessToken ){
if( strcmp(zVal,g.zAccessToken)==0 ){
accessTokenSeen = 1;
}
}
}
#if 0
else if( strcmp(zFieldName,"referer:")==0 ){
cgi_setenv("HTTP_REFERER", zVal);
}else if( strcmp(zFieldName,"user-agent:")==0 ){
cgi_setenv("HTTP_USER_AGENT", zVal);
}
#endif
}
if( g.zAccessToken && !accessTokenSeen ){
forbidden_request();
}
cgi_init();
}
#if INTERFACE
/*
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_STDIN 0x0002 /* Monitor stdin for "quit" */
#endif /* INTERFACE */
/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/
#define MAX_PARALLEL 2
/*
** Implement an HTTP server daemon listening on port iPort.
**
** As new connections arrive, fork a child and let child return
** out of this procedure call. The child will handle the request.
** The parent never returns from this procedure.
**
** Return 0 to each child as it runs. If unable to establish a
** listening socket, return non-zero.
*/
int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){
#ifdef __MINGW32__
/* Use win32_http_server() instead */
fossil_exit(1);
#else
int listener = -1; /* The server socket */
int connection; /* A socket for each individual connection */
fd_set readfds; /* Set of file descriptors for select() */
size_t lenaddr; /* Length of the inaddr structure */
int child; /* PID of the child process */
int nchildren = 0; /* Number of child processes */
struct timeval delay; /* How long to wait inside select() */
struct sockaddr_in inaddr; /* The socket address */
int opt = 1; /* setsockopt flag */
int iPort = mnPort;
while( iPort<=mxPort ){
memset(&inaddr, 0, sizeof(inaddr));
inaddr.sin_family = AF_INET;
if( flags & HTTP_SERVER_LOCALHOST ){
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}else{
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
inaddr.sin_port = htons(iPort);
listener = socket(AF_INET, SOCK_STREAM, 0);
if( listener<0 ){
iPort++;
continue;
}
|
| ︙ | ︙ | |||
1224 1225 1226 1227 1228 1229 1230 |
/* Slow down if connections are arriving too fast */
sleep( nchildren-MAX_PARALLEL );
}
delay.tv_sec = 60;
delay.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET( listener, &readfds);
| > > > | > > > > > > > > > > > | 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 |
/* Slow down if connections are arriving too fast */
sleep( nchildren-MAX_PARALLEL );
}
delay.tv_sec = 60;
delay.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET( listener, &readfds);
if( flags & HTTP_SERVER_STDIN ){
FD_SET( 0, &readfds);
}
select( listener+1, &readfds, 0, 0, &delay);
if( FD_ISSET(0, &readfds) ){
int i;
char zIn[200];
assert( flags & HTTP_SERVER_STDIN );
zIn[0] = 0;
fgets(zIn, sizeof(zIn), stdin);
for(i=0; zIn[i] && zIn[i]!='\n'; i++){}
zIn[i] = 0;
if( strcmp(zIn, "quit")==0 || feof(stdin) ) fossil_exit(0);
}
if( FD_ISSET(listener, &readfds) ){
lenaddr = sizeof(inaddr);
connection = accept(listener, (struct sockaddr*)&inaddr,
(socklen_t*) &lenaddr);
if( connection>=0 ){
child = fork();
if( child!=0 ){
if( child>0 ) nchildren++;
|
| ︙ | ︙ |
Changes to src/config.h.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <ctype.h> #include <string.h> #include <stdarg.h> #include <assert.h> #ifdef __MINGW32__ # include <windows.h> #else # include <pwd.h> #endif #include "sqlite3.h" /* ** Typedef for a 64-bit integer | > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #include <ctype.h> #include <string.h> #include <stdarg.h> #include <assert.h> #ifdef __MINGW32__ # include <windows.h> #else # include <sys/types.h> # include <signal.h> # include <pwd.h> #endif #include "sqlite3.h" /* ** Typedef for a 64-bit integer |
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
109 110 111 112 113 114 115 |
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpTrace ){
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
}
| | > > > > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpTrace ){
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
}
blob_appendf(pHdr, "Content-Length: %d\r\n", blob_size(pPayload));
if( g.zAccessToken ){
blob_appendf(pHdr, "X-Fossil-Access-Token: %s\r\n", g.zAccessToken);
}
blob_appendf(pHdr, "\r\n");
}
/*
** Sign the content in pSend, compress it, and send it to the server
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
** in pRecv. pRecv is assumed to be uninitialized when
** this routine is called - this routine will initialize it.
|
| ︙ | ︙ |
Changes to src/http_transport.c.
| ︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
if( pnSent ) *pnSent = transport.nSent;
if( pnRcvd ) *pnRcvd = transport.nRcvd;
if( resetFlag ){
transport.nSent = 0;
transport.nRcvd = 0;
}
}
/*
** Open a connection to the server. The server is defined by the following
** global variables:
**
** g.urlName Name of the server. Ex: www.fossil-scm.org
** g.urlPort TCP/IP port. Ex: 80
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
if( pnSent ) *pnSent = transport.nSent;
if( pnRcvd ) *pnRcvd = transport.nRcvd;
if( resetFlag ){
transport.nSent = 0;
transport.nRcvd = 0;
}
}
/*
** Global initialization of the transport layer
*/
void transport_global_startup(void){
if( g.urlIsSsh ){
char *zCmd;
int i;
char zIn[200];
#ifdef __MINGW32__
fossil_fatal("the ssh:// sync method is currently only supported on unix");
#endif
if( g.urlUser && g.urlUser[0] ){
zCmd = mprintf(
"ssh -L127.0.0.1:%d:127.0.0.1:%d %s@%s "
"\"fossil server -P %d '%s'\"",
g.urlPort, g.urlPort, g.urlUser, g.urlSshHost, g.urlPort, g.urlPath
);
}else{
zCmd = mprintf(
"ssh -L127.0.0.1:%d:127.0.0.1:%d %s \"fossil sshd -P %d '%s'\"",
g.urlPort, g.urlPort, g.urlSshHost, g.urlPort, g.urlPath
);
}
printf("%s\n", zCmd);
popen2(zCmd, &g.sshIn, &g.sshOut, &g.sshPid);
if( g.sshPid==0 ){
fossil_fatal("cannot start ssh tunnel using [%s]", zCmd);
}
free(zCmd);
zIn[0] = 0;
fgets(zIn, sizeof(zIn), g.sshIn);
for(i=0; zIn[i] && zIn[i]!='\n'; i++){}
zIn[i] = 0;
if( memcmp(zIn, "Access-Token: ", 14)!=0 ){
pclose2(g.sshIn, g.sshOut, g.sshPid);
fossil_fatal("failed to start ssh tunnel");
}
g.zAccessToken = mprintf("%s", &zIn[14]);
}
}
/*
** Open a connection to the server. The server is defined by the following
** global variables:
**
** g.urlName Name of the server. Ex: www.fossil-scm.org
** g.urlPort TCP/IP port. Ex: 80
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
i++;
}
/* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
return &transport.pBuf[iStart];
}
void transport_global_shutdown(void){
if( g.urlIsHttps ){
#ifdef FOSSIL_ENABLE_SSL
ssl_global_shutdown();
#endif
}else{
socket_global_shutdown();
}
}
| > > > > > > | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
i++;
}
/* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
return &transport.pBuf[iStart];
}
void transport_global_shutdown(void){
if( g.urlIsSsh && g.sshPid ){
printf("Closing SSH tunnel: ");
fflush(stdout);
pclose2(g.sshIn, g.sshOut, g.sshPid);
g.sshPid = 0;
}
if( g.urlIsHttps ){
#ifdef FOSSIL_ENABLE_SSL
ssl_global_shutdown();
#endif
}else{
socket_global_shutdown();
}
}
|
Changes to src/main.c.
| ︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | Th_Interp *interp; /* The TH1 interpreter */ FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ int urlIsFile; /* True if a "file:" url */ int urlIsHttps; /* True if a "https:" url */ char *urlName; /* Hostname for http: or filename for file: */ char *urlHostname; /* The HOST: parameter on http headers */ char *urlProtocol; /* "http" or "https" */ int urlPort; /* TCP port number for http: or https: */ int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ int dontKeepUrl; /* Do not persist the URL */ | > > > > > > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | Th_Interp *interp; /* The TH1 interpreter */ FILE *httpIn; /* Accept HTTP input from here */ FILE *httpOut; /* Send HTTP output here */ int xlinkClusterOnly; /* Set when cloning. Only process clusters */ int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ int *aCommitFile; /* Array of files to be committed */ int markPrivate; /* All new artifacts are private if true */ char *zAccessToken; /* X-Fossil-Access-Token HTTP header field */ int sshPid; /* Process id of ssh subprocess */ FILE *sshIn; /* From ssh subprocess to this */ FILE *sshOut; /* From this to ssh subprocess */ int urlIsFile; /* True if a "file:" url */ int urlIsHttps; /* True if a "https:" url */ int urlIsSsh; /* True if an "ssh:" url */ char *urlName; /* Hostname for http: or filename for file: */ char *urlSshHost; /* Hostname for ssh: tunnels */ char *urlHostname; /* The HOST: parameter on http headers */ char *urlProtocol; /* "http" or "https" */ int urlPort; /* TCP port number for http: or https: */ int urlDfltPort; /* The default port for the given protocol */ int urlSshPort; /* TCP port for SSH */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ int dontKeepUrl; /* Do not persist the URL */ |
| ︙ | ︙ | |||
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | } return 0; } #endif #endif /* ** COMMAND: server ** COMMAND: ui ** ** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY? ** Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY? ** ** Open a socket and begin listening and responding to HTTP requests on ** TCP port 8080, or on any other TCP port defined by the -P or ** --port option. The optional argument is the name of the repository. ** The repository argument may be omitted if the working directory is ** within an open checkout. ** ** The "ui" command automatically starts a web browser after initializing | > | > > > > > > > > > > > > > > > > > > | 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 |
}
return 0;
}
#endif
#endif
/*
** COMMAND: sshd
** COMMAND: server
** COMMAND: ui
**
** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
** Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or
** --port option. The optional argument is the name of the repository.
** The repository argument may be omitted if the working directory is
** within an open checkout.
**
** The "ui" command automatically starts a web browser after initializing
** the web server. The "ui" command also binds to 127.0.0.1 and so will
** only process HTTP traffic from the local machine.
**
** In the "server" command, the REPOSITORY can be a directory (aka folder)
** that contains one or more respositories with names ending in ".fossil".
** In that case, the first element of the URL is used to select among the
** various repositories.
**
** The "ui" or "server" verb can also be "sshd". This is used internally
** by the ssh:// sync method.
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
const char *zPort; /* Value of the --port option */
char *zBrowser; /* Name of web browser program */
char *zBrowserCmd = 0; /* Command to launch the web browser */
int isUiCmd; /* True if command is "ui", not "server' */
const char *zNotFound; /* The --notfound option or NULL */
int flags = 0; /* Server flags */
#ifdef __MINGW32__
const char *zStopperFile; /* Name of file used to terminate server */
zStopperFile = find_option("stopper", 0, 1);
#endif
g.thTrace = find_option("th-trace", 0, 0)!=0;
if( g.thTrace ){
blob_zero(&g.thLog);
}
zPort = find_option("port", "P", 1);
zNotFound = find_option("notfound", 0, 1);
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
isUiCmd = g.argv[1][0]=='u';
if( isUiCmd ) flags |= HTTP_SERVER_LOCALHOST;
find_server_repository(isUiCmd);
if( zPort ){
iPort = mxPort = atoi(zPort);
}else{
iPort = db_get_int("http-port", 8080);
mxPort = iPort+100;
}
if( g.argv[1][0]=='s' && g.argv[1][1]=='s' ){
/* For ssh://, output a random "access token" that must appear in
** the header of every HTTP request. HTTP requests without the
** correct access token reply with 403 Forbidden. The access token
** prevents any clients other than the one client that launched the
** remote server via SSH from accessing the remote server.
*/
g.zAccessToken = db_text(0, "SELECT lower(hex(randomblob(20)))");
printf("Access-Token: %s\n", g.zAccessToken);
fflush(stdout);
flags |= HTTP_SERVER_LOCALHOST | HTTP_SERVER_STDIN;
}
#ifndef __MINGW32__
/* Unix implementation */
if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__)
zBrowser = db_get("web-browser", 0);
if( zBrowser==0 ){
static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
|
| ︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 |
}
#else
zBrowser = db_get("web-browser", "open");
#endif
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
}
db_close();
| | | | 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
}
#else
zBrowser = db_get("web-browser", "open");
#endif
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
}
db_close();
if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
fossil_fatal("unable to listen on TCP socket %d", iPort);
}
g.httpIn = stdin;
g.httpOut = stdout;
if( g.fHttpTrace || g.fSqlTrace ){
fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
}
g.cgiOutput = 1;
find_server_repository(isUiCmd);
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
cgi_handle_http_request(0);
process_one_web_page(zNotFound);
#else
/* Win32 implementation */
if( isUiCmd ){
zBrowser = db_get("web-browser", "start");
zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
}
db_close();
win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound, flags);
#endif
}
|
Changes to src/main.mk.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/name.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ | > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ $(SRCDIR)/name.c \ $(SRCDIR)/pivot.c \ $(SRCDIR)/popen.c \ $(SRCDIR)/pqueue.c \ $(SRCDIR)/printf.c \ $(SRCDIR)/rebuild.c \ $(SRCDIR)/report.c \ $(SRCDIR)/rss.c \ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ |
| ︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 130 131 132 133 134 | main_.c \ manifest_.c \ md5_.c \ merge_.c \ merge3_.c \ name_.c \ pivot_.c \ pqueue_.c \ printf_.c \ rebuild_.c \ report_.c \ rss_.c \ schema_.c \ search_.c \ | > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | main_.c \ manifest_.c \ md5_.c \ merge_.c \ merge3_.c \ name_.c \ pivot_.c \ popen_.c \ pqueue_.c \ printf_.c \ rebuild_.c \ report_.c \ rss_.c \ schema_.c \ search_.c \ |
| ︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 | $(OBJDIR)/main.o \ $(OBJDIR)/manifest.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/name.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/rebuild.o \ $(OBJDIR)/report.o \ $(OBJDIR)/rss.o \ $(OBJDIR)/schema.o \ $(OBJDIR)/search.o \ | > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | $(OBJDIR)/main.o \ $(OBJDIR)/manifest.o \ $(OBJDIR)/md5.o \ $(OBJDIR)/merge.o \ $(OBJDIR)/merge3.o \ $(OBJDIR)/name.o \ $(OBJDIR)/pivot.o \ $(OBJDIR)/popen.o \ $(OBJDIR)/pqueue.o \ $(OBJDIR)/printf.o \ $(OBJDIR)/rebuild.o \ $(OBJDIR)/report.o \ $(OBJDIR)/rss.o \ $(OBJDIR)/schema.o \ $(OBJDIR)/search.o \ |
| ︙ | ︙ | |||
268 269 270 271 272 273 274 | # $(SRCDIR)/../manifest: # noop clean: rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers | | | | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | # $(SRCDIR)/../manifest: # noop clean: rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h page_index.h: $(TRANS_SRC) mkindex ./mkindex $(TRANS_SRC) >$@ headers: page_index.h makeheaders VERSION.h ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h touch headers headers: Makefile Makefile: add_.c: $(SRCDIR)/add.c translate ./translate $(SRCDIR)/add.c >add_.c $(OBJDIR)/add.o: add_.c add.h $(SRCDIR)/config.h |
| ︙ | ︙ | |||
557 558 559 560 561 562 563 564 565 566 567 568 569 570 | pivot_.c: $(SRCDIR)/pivot.c translate ./translate $(SRCDIR)/pivot.c >pivot_.c $(OBJDIR)/pivot.o: pivot_.c pivot.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pivot.o -c pivot_.c pivot.h: headers pqueue_.c: $(SRCDIR)/pqueue.c translate ./translate $(SRCDIR)/pqueue.c >pqueue_.c $(OBJDIR)/pqueue.o: pqueue_.c pqueue.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pqueue.o -c pqueue_.c pqueue.h: headers | > > > > > > > | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | pivot_.c: $(SRCDIR)/pivot.c translate ./translate $(SRCDIR)/pivot.c >pivot_.c $(OBJDIR)/pivot.o: pivot_.c pivot.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pivot.o -c pivot_.c pivot.h: headers popen_.c: $(SRCDIR)/popen.c translate ./translate $(SRCDIR)/popen.c >popen_.c $(OBJDIR)/popen.o: popen_.c popen.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/popen.o -c popen_.c popen.h: headers pqueue_.c: $(SRCDIR)/pqueue.c translate ./translate $(SRCDIR)/pqueue.c >pqueue_.c $(OBJDIR)/pqueue.o: pqueue_.c pqueue.h $(SRCDIR)/config.h $(XTCC) -o $(OBJDIR)/pqueue.o -c pqueue_.c pqueue.h: headers |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | main manifest md5 merge merge3 name pivot pqueue printf rebuild report rss schema search | > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search |
| ︙ | ︙ |
Added src/popen.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
/*
** Copyright (c) 2010 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file contains an implementation of a bi-directional popen().
*/
#include "config.h"
#include "popen.h"
/*
** Create a child process running shell command "zCmd". *ppOut is
** a FILE that becomes the standard input of the child process.
** (The caller writes to *ppOut in order to send text to the child.)
** *ppIn is stdout from the child process. (The caller
** reads from *ppIn in order to receive input from the child.)
** The process ID of the child is written into *pChildPid.
**
** Return the number of errors.
*/
int popen2(const char *zCmd, FILE **ppIn, FILE **ppOut, int *pChildPid){
#ifdef __MINGW32__
return 1; /* Not implemented on windows, yet */
#else
int pin[2], pout[2];
*ppIn = 0;
*ppOut = 0;
*pChildPid = 0;
if( pipe(pin)<0 ){
return 1;
}
if( pipe(pout)<0 ){
close(pin[0]);
close(pin[1]);
return 1;
}
*pChildPid = fork();
if( *pChildPid<0 ){
close(pin[0]);
close(pin[1]);
close(pout[0]);
close(pout[1]);
*pChildPid = 0;
return 1;
}
if( *pChildPid==0 ){
/* This is the child process */
close(0);
dup(pout[0]);
close(pout[0]);
close(pout[1]);
close(1);
dup(pin[1]);
close(pin[0]);
close(pin[1]);
execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
return 1;
}else{
/* This is the parent process */
close(pin[1]);
*ppIn = fdopen(pin[0], "r");
close(pout[0]);
*ppOut = fdopen(pout[1], "w");
return 0;
}
#endif
}
/*
** Close the connection to a child process previously created using
** popen2(). Kill off the child process, then close the pipes.
*/
void pclose2(FILE *pIn, FILE *pOut, int childPid){
#ifdef __MINGW32__
/* Not implemented, yet */
#else
kill(childPid, SIGINT);
fclose(pIn);
fclose(pOut);
#endif
}
|
Changes to src/url.c.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
**
*******************************************************************************
**
** This file contains code for parsing URLs that appear on the command-line
*/
#include "config.h"
#include "url.h"
/*
** Parse the given URL. Populate variables in the global "g" structure.
**
** g.urlIsFile True if FILE:
** g.urlIsHttps True if HTTPS:
** g.urlProtocol "http" or "https" or "file"
** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE:
** g.urlPort TCP port number for HTTP or HTTPS.
** g.urlDfltPort Default TCP port number (80 or 443).
** g.urlPath Path name for HTTP or HTTPS.
** g.urlUser Userid.
** g.urlPasswd Password.
** g.urlHostname HOST:PORT or just HOST if port is the default.
** g.urlCanonical The URL in canonical form, omitting the password
**
** HTTP url format is:
**
** http://userid:password@host:port/path?query#fragment
**
*/
void url_parse(const char *zUrl){
int i, j, c;
char *zFile = 0;
if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
int iStart;
char *zLogin;
| > > > > > > > > > > > > > > > > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
**
*******************************************************************************
**
** This file contains code for parsing URLs that appear on the command-line
*/
#include "config.h"
#include "url.h"
/*
** Convert a string to lower-case.
*/
static void url_tolower(char *z){
while( *z ){
*z = tolower(*z);
z++;
}
}
/*
** Parse the given URL. Populate variables in the global "g" structure.
**
** g.urlIsFile True if FILE:
** g.urlIsHttps True if HTTPS:
** g.urlIsSsh True if SSH:
** g.urlProtocol "http" or "https" or "file"
** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE:
** g.urlSshHost Hostname for SSH: tunnel
** g.urlPort TCP port number for HTTP or HTTPS.
** g.urlDfltPort Default TCP port number (80 or 443).
** g.urlSshPort TCP port for SSH: tunnel
** g.urlPath Path name for HTTP or HTTPS.
** g.urlUser Userid.
** g.urlPasswd Password.
** g.urlHostname HOST:PORT or just HOST if port is the default.
** g.urlCanonical The URL in canonical form, omitting the password
**
** HTTP url format is:
**
** http://userid:password@host:port/path?query#fragment
**
** SSH url format is:
**
** ssh://userid@host:port/fullpath
**
*/
void url_parse(const char *zUrl){
int i, j, c;
char *zFile = 0;
if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
int iStart;
char *zLogin;
|
| ︙ | ︙ | |||
68 69 70 71 72 73 74 |
dehttpize(g.urlPasswd);
}
for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
i = j;
zLogin = mprintf("%t@", g.urlUser);
}else{
| < | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
dehttpize(g.urlPasswd);
}
for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
i = j;
zLogin = mprintf("%t@", g.urlUser);
}else{
g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
zLogin = mprintf("");
}
url_tolower(g.urlName);
if( c==':' ){
g.urlPort = 0;
i++;
while( (c = zUrl[i])!=0 && isdigit(c) ){
g.urlPort = g.urlPort*10 + c - '0';
i++;
}
|
| ︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
);
}else{
g.urlCanonical = mprintf(
"%s://%s%T:%d%T",
g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
);
}
free(zLogin);
}else if( strncmp(zUrl, "file:", 5)==0 ){
g.urlIsFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;
}else{
i = 5;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
);
}else{
g.urlCanonical = mprintf(
"%s://%s%T:%d%T",
g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
);
}
free(zLogin);
}else if( strncmp(zUrl, "ssh://", 6)==0 ){
char *zLogin;
int r;
g.urlIsFile = 0;
g.urlIsSsh = 1;
g.urlProtocol = "ssh";
sqlite3_randomness(sizeof(r), &r);
g.urlPort = 18800 + (r & 0x7fffff)%2000;
g.urlDfltPort = 80;
g.urlName = "127.0.0.1";
g.urlHostname = g.urlName;
for(i=6; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
if( c=='@' ){
for(j=6; j<i && zUrl[j]!=':'; j++){}
g.urlUser = mprintf("%.*s", j-6, &zUrl[6]);
dehttpize(g.urlUser);
if( j<i ){
g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
dehttpize(g.urlPasswd);
}
for(j=i+1; (c=zUrl[j])!=0 && c!='/'; j++){}
g.urlSshHost = mprintf("%.*s", j-i-1, &zUrl[i+1]);
i = j;
zLogin = mprintf("%t@", g.urlUser);
}else{
g.urlSshHost = mprintf("%.*s", i-6, &zUrl[6]);
zLogin = mprintf("");
}
url_tolower(g.urlSshHost);
g.urlPath = mprintf(&zUrl[i+1]);
dehttpize(g.urlPath);
g.urlCanonical = mprintf(
"ssh://%s%T/%T",
zLogin, g.urlSshHost, g.urlPath
);
free(zLogin);
}else if( strncmp(zUrl, "file:", 5)==0 ){
g.urlIsFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;
}else{
i = 5;
|
| ︙ | ︙ | |||
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
if( g.argc!=3 && g.argc!=4 ){
usage("URL");
}
url_parse(g.argv[2]);
for(i=0; i<2; i++){
printf("g.urlIsFile = %d\n", g.urlIsFile);
printf("g.urlIsHttps = %d\n", g.urlIsHttps);
printf("g.urlProtocol = %s\n", g.urlProtocol);
printf("g.urlName = %s\n", g.urlName);
printf("g.urlPort = %d\n", g.urlPort);
printf("g.urlDfltPort = %d\n", g.urlDfltPort);
printf("g.urlHostname = %s\n", g.urlHostname);
printf("g.urlPath = %s\n", g.urlPath);
printf("g.urlUser = %s\n", g.urlUser);
printf("g.urlPasswd = %s\n", g.urlPasswd);
printf("g.urlCanonical = %s\n", g.urlCanonical);
if( i==0 ){
printf("********\n");
url_enable_proxy("Using proxy: ");
}
}
}
| > > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
if( g.argc!=3 && g.argc!=4 ){
usage("URL");
}
url_parse(g.argv[2]);
for(i=0; i<2; i++){
printf("g.urlIsFile = %d\n", g.urlIsFile);
printf("g.urlIsHttps = %d\n", g.urlIsHttps);
printf("g.urlIsSsh = %d\n", g.urlIsSsh);
printf("g.urlProtocol = %s\n", g.urlProtocol);
printf("g.urlName = %s\n", g.urlName);
printf("g.urlSshHost = %s\n", g.urlSshHost);
printf("g.urlPort = %d\n", g.urlPort);
printf("g.urlDfltPort = %d\n", g.urlDfltPort);
printf("g.urlHostname = %s\n", g.urlHostname);
printf("g.urlPath = %s\n", g.urlPath);
printf("g.urlUser = %s\n", g.urlUser);
printf("g.urlPasswd = %s\n", g.urlPasswd);
printf("g.urlCanonical = %s\n", g.urlCanonical);
if( g.urlIsFile || g.urlIsSsh ) break;
if( i==0 ){
printf("********\n");
url_enable_proxy("Using proxy: ");
}
}
}
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
131 132 133 134 135 136 137 | ** Start a listening socket and process incoming HTTP requests on ** that socket. */ void win32_http_server( int mnPort, int mxPort, /* Range of allowed TCP port numbers */ const char *zBrowser, /* Command to launch browser. (Or NULL) */ const char *zStopper, /* Stop server when this file is exists (Or NULL) */ | | > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
const char *zBrowser, /* Command to launch browser. (Or NULL) */
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
const char *zNotFound, /* The --notfound option, or NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
WSADATA wd;
SOCKET s = INVALID_SOCKET;
SOCKADDR_IN addr;
int idCnt = 0;
int iPort = mnPort;
char *zNotFoundOption;
|
| ︙ | ︙ | |||
156 157 158 159 160 161 162 |
while( iPort<=mxPort ){
s = socket(AF_INET, SOCK_STREAM, 0);
if( s==INVALID_SOCKET ){
fossil_fatal("unable to create a socket");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
| > > > | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
while( iPort<=mxPort ){
s = socket(AF_INET, SOCK_STREAM, 0);
if( s==INVALID_SOCKET ){
fossil_fatal("unable to create a socket");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
if( flags & HTTP_SERVER_LOCALHOST ){
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}else{
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
closesocket(s);
iPort++;
continue;
}
if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
closesocket(s);
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
nCardSent++;
}
if( pushFlag ){
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
nCardSent++;
}
manifest_crosslink_begin();
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
while( go ){
int newPhantom = 0;
char *zRandomness;
/* Send make the most recently received cookie. Let the server
| > | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 |
nCardSent++;
}
if( pushFlag ){
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
nCardSent++;
}
manifest_crosslink_begin();
transport_global_startup();
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
while( go ){
int newPhantom = 0;
char *zRandomness;
/* Send make the most recently received cookie. Let the server
|
| ︙ | ︙ |