Check-in [958f596637]
Not logged in

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

Overview
Comment:Continuing work on the ssh:// sync protocol.
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 958f59663701959705c820a645e42a12d95cf5f7
User & Date: drh 2010-08-25 16:03:21.000
Context
2010-08-25
17:00
The ssh:// sync method appears to work now, for linux-to-linux... check-in: 66cdaee68e user: drh tags: experimental
16:03
Continuing work on the ssh:// sync protocol. check-in: 958f596637 user: drh tags: experimental
14:03
Initial code to implement synchronization via ssh. check-in: b19f25fe87 user: drh tags: experimental
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/cgi.c.
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
      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-security-token:")==0 ){
      if( g.zAccessToken ){
        if( strcmp(zVal,g.zAccessToken)==0 ){
          accessTokenSeen = 1;
        }
      }
    }
#if 0







|







1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
      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
1250
1251
1252
1253
1254
1255
1256

1257










1258
1259
1260
1261
1262
1263
1264
      /* 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( select( listener+1, &readfds, 0, 0, &delay) ){










      lenaddr = sizeof(inaddr);
      connection = accept(listener, (struct sockaddr*)&inaddr,
                                    (socklen_t*) &lenaddr);
      if( connection>=0 ){
        child = fork();
        if( child!=0 ){
          if( child>0 ) nchildren++;







>
|
>
>
>
>
>
>
>
>
>
>







1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
      /* 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);
    FD_SET( 0, &readfds);
    select( listener+1, &readfds, 0, 0, &delay);
    if( FD_ISSET(0, &readfds) ){
      int i;
      char zIn[200];
      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 ) 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_transport.c.
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

/*
** Global initialization of the transport layer
*/
void transport_global_startup(void){
  if( g.urlIsSsh ){
    char *zCmd;
    int i, j;
    char zReply[200];
    if( g.urlUser && g.urlUser[0] ){
      zCmd = mprintf(
         "ssh -L127.0.0.1:%d:127.0.0.1:%d %s@%s \"fossil sshd -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);
    g.sshIn = popen(zCmd, "r");
    if( g.sshIn==0 ){
      fossil_fatal("cannot start ssh tunnel using [%s]", zCmd);
    }
    free(zCmd);
    zReply[0] = 0;
    fgets(zReply, sizeof(zReply), g.sshIn);
    if( zReply[0]==0 ){
      pclose(g.sshIn);
      fossil_fatal("unable to set up ssh tunnel");
    }
    if( memcmp(zReply, "Access-Token: ", 14)!=0 ){
      pclose(g.sshIn);
      fossil_fatal("ssh tunnel did not send back an access token");
    }
    for(i=14; isspace(zReply[i]); i++);
    for(j=i; isalnum(zReply[j]); j++);
    g.zAccessToken = mprintf("%.*s", j-i, &zReply[i]); 
  }
}

/*
** Open a connection to the server.  The server is defined by the following
** global variables:
**







|
|


|
>









|
|



|
|
|
|
<
<
|
|
|

<
<
|







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

/*
** Global initialization of the transport layer
*/
void transport_global_startup(void){
  if( g.urlIsSsh ){
    char *zCmd;
    int i;
    char zIn[200];
    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:
**
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
    i++;
  }
  /* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
  return &transport.pBuf[iStart];
}

void transport_global_shutdown(void){
  if( g.urlIsSsh && g.sshIn ){
    pclose(g.sshIn);
    g.sshIn = 0;
  }
  if( g.urlIsHttps ){
    #ifdef FOSSIL_ENABLE_SSL
    ssl_global_shutdown();
    #endif
  }else{
    socket_global_shutdown();
  }
}







|
|
|









349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    i++;
  }
  /* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
  return &transport.pBuf[iStart];
}

void transport_global_shutdown(void){
  if( g.urlIsSsh && g.sshPid ){
    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.
82
83
84
85
86
87
88

89

90
91
92
93
94
95
96
  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 */

  FILE *sshIn;            /* Result of popen("ssh") */


  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 */







>
|
>







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  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 */
972
973
974
975
976
977
978

979
980
981
982
983
984
985
  }
  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







>







974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
  }
  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
1019
1020
1021
1022
1023
1024
1025





1026
1027
1028
1029
1030
1031
1032
  isUiCmd = g.argv[1][0]=='u';
  find_server_repository(isUiCmd);
  if( zPort ){
    iPort = mxPort = atoi(zPort);
  }else{
    iPort = db_get_int("http-port", 8080);
    mxPort = iPort+100;





  }
#ifndef __MINGW32__
  /* Unix implementation */
  if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__)
    zBrowser = db_get("web-browser", 0);
    if( zBrowser==0 ){







>
>
>
>
>







1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  isUiCmd = g.argv[1][0]=='u';
  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' ){
    g.zAccessToken = db_text(0, "SELECT lower(hex(randomblob(20)))");
    printf("Access-Token: %s\n", g.zAccessToken);
    fflush(stdout);
  }
#ifndef __MINGW32__
  /* Unix implementation */
  if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__)
    zBrowser = db_get("web-browser", 0);
    if( zBrowser==0 ){
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
275
276
277
278
279
280
281
282
283
284
285
286
287
#
$(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 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 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







|




|







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
}