Check-in [dfb68976be]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the "ui" command to automatically launch a web browser after starting the HTTP server. The web browser choice can be configured using the "setting" command.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dfb68976be2232e5d3f202e041240e165afb978b
User & Date: drh 2008-05-17 18:19:11.000
Context
2008-05-17
19:24
Fix a bug in the new win32 server implementation. check-in: b9eec2d277 user: drh tags: trunk
18:19
Add the "ui" command to automatically launch a web browser after starting the HTTP server. The web browser choice can be configured using the "setting" command. check-in: dfb68976be user: drh tags: trunk
17:52
Make sure temporary files are well-named and are deleted after use in the win32 fossil server command. check-in: 24f336c9ae user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/cgi.c.
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
** 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 iPort){
#ifdef __MINGW32__
  fprintf(stderr,"server not yet available in windows version of fossil\n");
  exit(1);
#else
  int listener;                /* The server socket */
  int connection;              /* A socket for each individual connection */
  fd_set readfds;              /* Set of file descriptors for select() */







|







1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
** 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 iPort, char *zBrowser){
#ifdef __MINGW32__
  fprintf(stderr,"server not yet available in windows version of fossil\n");
  exit(1);
#else
  int listener;                /* The server socket */
  int connection;              /* A socket for each individual connection */
  fd_set readfds;              /* Set of file descriptors for select() */
1196
1197
1198
1199
1200
1201
1202



1203
1204
1205
1206
1207
1208
1209
  setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

  if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
    close(listener);
    return 1;
  }
  listen(listener,10);



  while( 1 ){
    if( nchildren>MAX_PARALLEL ){
      /* Slow down if connections are arriving too fast */
      sleep( nchildren-MAX_PARALLEL );
    }
    delay.tv_sec = 60;
    delay.tv_usec = 0;







>
>
>







1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
  setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

  if( bind(listener, (struct sockaddr*)&inaddr, sizeof(inaddr))<0 ){
    close(listener);
    return 1;
  }
  listen(listener,10);
  if( zBrowser ){
    system(zBrowser);
  }
  while( 1 ){
    if( nchildren>MAX_PARALLEL ){
      /* Slow down if connections are arriving too fast */
      sleep( nchildren-MAX_PARALLEL );
    }
    delay.tv_sec = 60;
    delay.tv_usec = 0;
Changes to src/db.c.
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103



1104
1105
1106
1107
1108
1109
1110
1111



1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
**
** The "unset" command clears a property setting.
**
**    autosync         If enabled, automatically pull prior to
**                     commit or update and automatically push
**                     after commit or tag or branch creation.
**
**    pgp-command      Command used to clear-sign manifests at check-in.
**                     The default is "gpg --clearsign -o ".
**
**    editor           Text editor command used for check-in comments.



**
**    localauth        If enabled, require that HTTP connections from
**                     127.0.0.1 be authenticated by password.  If
**                     false, all HTTP requests from localhost have
**                     unrestricted access to the repository.
**
**    omitsign         When enabled, fossil will not attempt to sign any
**                     commit with gpg. All commits will be unsigned.



**
**    proxy            URL of the HTTP proxy.  If undefined or "off" then
**                     the "http_proxy" environment variable is consulted.
**                     If the http_proxy environment variable is undefined
**                     then a direct HTTP connection is used.
**
**    diff-command     External command to run when performing a diff.
**                     If undefined, the internal text diff will be used.
**
**    gdiff-command    External command to run when performing a graphical
**                     diff. If undefined, text diff will be used.
*/
void setting_cmd(void){
  static const char *azName[] = {
    "autosync",
    "diff-command",
    "editor",
    "gdiff-command",
    "localauth",
    "omitsign",
    "pgp-command",
    "proxy",

  };
  int i;
  int globalFlag = find_option("global","g",0)!=0;
  int unsetFlag = g.argv[1][0]=='u';
  db_find_and_open_repository(0);
  if( !g.repositoryOpen ){
    db_open_config();







|
|


>
>
>








>
>
>






|
|
|
<
|











>







1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
**
** The "unset" command clears a property setting.
**
**    autosync         If enabled, automatically pull prior to
**                     commit or update and automatically push
**                     after commit or tag or branch creation.
**
**    diff-command     External command to run when performing a diff.
**                     If undefined, the internal text diff will be used.
**
**    editor           Text editor command used for check-in comments.
**
**    gdiff-command    External command to run when performing a graphical
**                     diff. If undefined, text diff will be used.
**
**    localauth        If enabled, require that HTTP connections from
**                     127.0.0.1 be authenticated by password.  If
**                     false, all HTTP requests from localhost have
**                     unrestricted access to the repository.
**
**    omitsign         When enabled, fossil will not attempt to sign any
**                     commit with gpg. All commits will be unsigned.
**
**    pgp-command      Command used to clear-sign manifests at check-in.
**                     The default is "gpg --clearsign -o ".
**
**    proxy            URL of the HTTP proxy.  If undefined or "off" then
**                     the "http_proxy" environment variable is consulted.
**                     If the http_proxy environment variable is undefined
**                     then a direct HTTP connection is used.
**
**    web-browser      A shell command used to launch your preferred
**                     web browser when given a URL as an argument.
**                     Defaults to "start" on windows, "open" on Mac,

**                     and "firefox" on Unix.
*/
void setting_cmd(void){
  static const char *azName[] = {
    "autosync",
    "diff-command",
    "editor",
    "gdiff-command",
    "localauth",
    "omitsign",
    "pgp-command",
    "proxy",
    "web-browser",
  };
  int i;
  int globalFlag = find_option("global","g",0)!=0;
  int unsetFlag = g.argv[1][0]=='u';
  db_find_and_open_repository(0);
  if( !g.repositoryOpen ){
    db_open_config();
Changes to src/main.c.
648
649
650
651
652
653
654

655
656

657
658
659
660
661
662



663
664
665
666


667
668
669
670
671
672
673
674
675
676
677
678
679
680








681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698




699
700
701
void cmd_test_http(void){
  login_set_capabilities("s");
  cmd_http();
}

/*
** COMMAND: server

**
** Usage: %fossil server ?-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.



*/
void cmd_webserver(void){
  int iPort;
  const char *zPort;



  zPort = find_option("port", "P", 1);
  if( zPort ){
    iPort = atoi(zPort);
  }else{
    iPort = 8080;
  }
  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
  if( g.argc==2 ){
    db_must_be_within_tree();
    db_close();
  }
#ifndef __MINGW32__
  /* Unix implementation */








  if( cgi_http_server(iPort) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiPanic = 1;
  if( g.argc==2 ){
    db_must_be_within_tree();
  }else{
    db_open_repository(g.argv[2]);
  }
  cgi_handle_http_request(0);
  process_one_web_page();
#else
  /* Win32 implementation */




  win32_http_server(iPort);
#endif
}







>


>






>
>
>




>
>














>
>
>
>
>
>
>
>
|

















>
>
>
>
|


648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
void cmd_test_http(void){
  login_set_capabilities("s");
  cmd_http();
}

/*
** 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.
*/
void cmd_webserver(void){
  int iPort;
  const char *zPort;
  char *zBrowser;
  char *zBrowserCmd = 0;

  zPort = find_option("port", "P", 1);
  if( zPort ){
    iPort = atoi(zPort);
  }else{
    iPort = 8080;
  }
  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
  if( g.argc==2 ){
    db_must_be_within_tree();
    db_close();
  }
#ifndef __MINGW32__
  /* Unix implementation */
  if( g.argv[1][0]=='u' ){
#if !defined(__DARWIN__) && !defined(__APPLE__)
    zBrowser = db_get("web-browser", "firefox");
#else
    zBrowser = db_get("web-browser", "open");
#endif
    zBrowserCmd = mprintf("%s http://localhost:%d/ &", zBrowser, iPort);
  }
  if( cgi_http_server(iPort, zBrowserCmd) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiPanic = 1;
  if( g.argc==2 ){
    db_must_be_within_tree();
  }else{
    db_open_repository(g.argv[2]);
  }
  cgi_handle_http_request(0);
  process_one_web_page();
#else
  /* Win32 implementation */
  if( g.argv[1][0]=='u' ){
    zBrowser = db_get("web-browser", "start");
    zBrowserCmd = mprintf("%s http://127.0.0.1:%d/", zBrowser, iPort);
  }
  win32_http_server(iPort, zBrowserCmd);
#endif
}
Changes to src/winhttp.c.
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  free(p);
}

/*
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(int iPort){
  WSADATA wd;
  SOCKET s;
  SOCKADDR_IN addr;
  int idCnt = 0;

  if( WSAStartup(MAKEWORD(1,1), &wd) ){
    fossil_fatal("unable to initialize winsock");







|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  free(p);
}

/*
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(int iPort, char *zBrowser){
  WSADATA wd;
  SOCKET s;
  SOCKADDR_IN addr;
  int idCnt = 0;

  if( WSAStartup(MAKEWORD(1,1), &wd) ){
    fossil_fatal("unable to initialize winsock");
157
158
159
160
161
162
163






164
165
166
167
168
169
170
    closesocket(s);
    fossil_fatal("unable to bind");
  }
  if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
    closesocket(s);
    fossil_fatal("unable to listen");
  }






  for(;;){
    SOCKET client;
    SOCKADDR_IN client_addr;
    HttpRequest *p;
    int len = sizeof(client_addr);

    client = accept(s, (struct sockaddr*)&client_addr, &len);







>
>
>
>
>
>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    closesocket(s);
    fossil_fatal("unable to bind");
  }
  if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
    closesocket(s);
    fossil_fatal("unable to listen");
  }
  printf("Listening for HTTP requests on TCP port %d\n", iPort);
  if( zBrowser ){
    printf("Launch webbrowser: %s\n", zBrowser);
    system(zBrowser);
  }
  printf("Type Ctrl-C to stop the HTTP server\n");
  for(;;){
    SOCKET client;
    SOCKADDR_IN client_addr;
    HttpRequest *p;
    int len = sizeof(client_addr);

    client = accept(s, (struct sockaddr*)&client_addr, &len);