...
|
...
|
@@ -23,6 +23,7 @@
|
23
|
23
|
#include <sys/select.h>
|
24
|
24
|
#include <stdarg.h>
|
25
|
25
|
#include <sys/stat.h>
|
|
26
|
+#include <limits.h>
|
26
|
27
|
|
27
|
28
|
#include "re_data.h"
|
28
|
29
|
#include "re_plugin_unsaved.h"
|
...
|
...
|
@@ -43,6 +44,7 @@
|
43
|
44
|
#define COMMBUFSIZE 16384
|
44
|
45
|
#define COMMCLIENTSBLOCKSIZE 32
|
45
|
46
|
#define SOCKETFILENAMESIZE 1024
|
|
47
|
+#define MAXFILENAMESIZE PATH_MAX+1
|
46
|
48
|
#define LISTENBACKLOG 5
|
47
|
49
|
|
48
|
50
|
#define VIEWONLYPROGNAME "review"
|
...
|
...
|
@@ -181,6 +183,8 @@ typedef struct theme_t {
|
181
|
183
|
|
182
|
184
|
typedef struct commclient_t {
|
183
|
185
|
int fd;
|
|
186
|
+ int flag_connectedtoserver;
|
|
187
|
+ char remoteid[MAXFILENAMESIZE];
|
184
|
188
|
int sizebufin;
|
185
|
189
|
int usedbufin;
|
186
|
190
|
int gotbufin;
|
...
|
...
|
@@ -193,6 +197,7 @@ typedef struct commclient_t {
|
193
|
197
|
|
194
|
198
|
typedef struct comms_t {
|
195
|
199
|
int serverfd;
|
|
200
|
+ char id[MAXFILENAMESIZE];
|
196
|
201
|
char socketfilename[SOCKETFILENAMESIZE];
|
197
|
202
|
int sizeclients;
|
198
|
203
|
int usedclients;
|
...
|
...
|
@@ -294,7 +299,7 @@ int re_wheelaccel(re_t *re, int rawamount);
|
294
|
299
|
int re_themeset(re_t *re, int ntheme);
|
295
|
300
|
int re_socketinit(re_t *re, char *filename);
|
296
|
301
|
void re_socketfree(re_t *re);
|
297
|
|
-int re_socketnewclient(re_t *re);
|
|
302
|
+int re_socketnewclient(re_t *re, int alreadyacceptedfd);
|
298
|
303
|
int re_socketstep(re_t *re);
|
299
|
304
|
int re_socketin(re_t *re, int nclient, char *line);
|
300
|
305
|
#ifndef __GNUC__
|
...
|
...
|
@@ -2982,6 +2987,13 @@ re_socketinit(re_t *re,char *filename)
|
2982
|
2987
|
}
|
2983
|
2988
|
re->comms.usedclients=0;
|
2984
|
2989
|
}
|
|
2990
|
+ /* fill the id */
|
|
2991
|
+ if(realpath(filename,re->comms.id)==NULL) {
|
|
2992
|
+ /* if the path cannot be resolved, copy the filename */
|
|
2993
|
+ strncpy(re->comms.id,filename,sizeof(re->comms.id));
|
|
2994
|
+ re->comms.id[sizeof(re->comms.id)-1]='\0';
|
|
2995
|
+ }
|
|
2996
|
+ re->comms.id[sizeof(re->comms.id)-1]='\0';
|
2985
|
2997
|
/* prepare the new filepath for the socket */
|
2986
|
2998
|
if((passwd=getpwuid(getuid()))==NULL || (username=passwd->pw_name)==NULL) {
|
2987
|
2999
|
fprintf(stderr,"WARNING: Couldn't get username\n");
|
...
|
...
|
@@ -3000,16 +3012,39 @@ re_socketinit(re_t *re,char *filename)
|
3000
|
3012
|
return(-1);
|
3001
|
3013
|
}
|
3002
|
3014
|
/* detect if there is a stale socket */
|
3003
|
|
- if((oldfd=open(comms->socketfilename, O_WRONLY|O_APPEND))!=-1) {
|
|
3015
|
+ if((errstr="create")==NULL
|
|
3016
|
+ || (oldfd=socket(AF_UNIX,SOCK_STREAM,0))==-1
|
|
3017
|
+ || (errstr="assing")==NULL /* this one never fails, just for completion */
|
|
3018
|
+ || (memset(&addr,0,sizeof(struct sockaddr_un)))==NULL
|
|
3019
|
+ || (addr.sun_family=AF_UNIX)!=AF_UNIX
|
|
3020
|
+ || strncpy(addr.sun_path,comms->socketfilename,sizeof(addr.sun_path))==NULL
|
|
3021
|
+ || (errstr="connect")==NULL
|
|
3022
|
+ || connect(oldfd,(struct sockaddr *)&addr,sizeof(addr))==-1
|
|
3023
|
+ ) {
|
|
3024
|
+#if 0
|
|
3025
|
+fprintf(stderr,"Check for other server result: %s fail.\n",errstr);
|
|
3026
|
+#endif
|
|
3027
|
+ close(oldfd),oldfd=-1; /* OK: the re is no server as couldn't connect */
|
|
3028
|
+ } else {
|
3004
|
3029
|
fd_set writeset;
|
3005
|
3030
|
struct timeval tv;
|
3006
|
3031
|
FD_ZERO(&writeset);
|
3007
|
3032
|
FD_SET(oldfd,&writeset);
|
3008
|
3033
|
tv.tv_sec=tv.tv_usec=0;
|
3009
|
3034
|
if(select(oldfd+1,NULL,&writeset,NULL,&tv)>0) {
|
|
3035
|
+ int nclient;
|
3010
|
3036
|
comms->socketfilename[0]='\0';
|
3011
|
|
- fprintf(stderr,"WARNING: There is a process using the communication socket for the file\n");
|
3012
|
|
-#warning TODO: if the unix domain socket is in use, connect to it and warn that I''m also able to service that filename, so (1) it forwards the petitions, and (2) be waware of when the other process quits to retake control of the unix domain socket
|
|
3037
|
+ nclient=re_socketnewclient(re,oldfd),oldfd=-1;
|
|
3038
|
+ if(nclient!=-1) {
|
|
3039
|
+ re_socketout(re,nclient,"id %s\n",comms->id);
|
|
3040
|
+ comms->clients[nclient]->flag_connectedtoserver=1;
|
|
3041
|
+#if 0
|
|
3042
|
+fprintf(stderr,"nclient:%i id:\"%s\".\n",nclient,comms->id);
|
|
3043
|
+fprintf(stderr,"Connected to server.\n");
|
|
3044
|
+#endif
|
|
3045
|
+ return(0);
|
|
3046
|
+ }
|
|
3047
|
+ fprintf(stderr,"WARNING: There is a process using the communication socket for the file and couldn't connect to it.\n");
|
3013
|
3048
|
return(-1);
|
3014
|
3049
|
}
|
3015
|
3050
|
close(oldfd),oldfd=-1;
|
...
|
...
|
@@ -3033,7 +3068,7 @@ re_socketinit(re_t *re,char *filename)
|
3033
|
3068
|
fprintf(stderr,"WARNING: Couldn't %s unix domain socket\n",errstr);
|
3034
|
3069
|
return(-1);
|
3035
|
3070
|
}
|
3036
|
|
-#if 1
|
|
3071
|
+#if 0
|
3037
|
3072
|
fprintf(stderr,"Server registered.\n");
|
3038
|
3073
|
#endif
|
3039
|
3074
|
return(0);
|
...
|
...
|
@@ -3066,7 +3101,7 @@ re_socketfree(re_t *re)
|
3066
|
3101
|
}
|
3067
|
3102
|
|
3068
|
3103
|
int
|
3069
|
|
-re_socketnewclient(re_t *re)
|
|
3104
|
+re_socketnewclient(re_t *re, int alreadyacceptedfd)
|
3070
|
3105
|
{
|
3071
|
3106
|
int i;
|
3072
|
3107
|
int fd;
|
...
|
...
|
@@ -3076,7 +3111,10 @@ re_socketnewclient(re_t *re)
|
3076
|
3111
|
addrlen=sizeof(addr);
|
3077
|
3112
|
if(re==NULL)
|
3078
|
3113
|
return(-1); /* sanity check failed */
|
3079
|
|
- fd=accept(re->comms.serverfd,&addr,&addrlen);
|
|
3114
|
+ if(alreadyacceptedfd==-1)
|
|
3115
|
+ fd=accept(re->comms.serverfd,&addr,&addrlen);
|
|
3116
|
+ else
|
|
3117
|
+ fd=alreadyacceptedfd;
|
3080
|
3118
|
if(re->comms.usedclients==re->comms.sizeclients) {
|
3081
|
3119
|
commclient_t **newclients;
|
3082
|
3120
|
if((newclients=realloc(re->comms.clients,sizeof(commclient_t *)*(re->comms.sizeclients+COMMCLIENTSBLOCKSIZE)))==NULL) {
|
...
|
...
|
@@ -3112,8 +3150,7 @@ re_socketnewclient(re_t *re)
|
3112
|
3150
|
client->usedbufin=client->gotbufin=0;
|
3113
|
3151
|
client->usedbufout=client->gotbufout=0;
|
3114
|
3152
|
re->comms.usedclients++;
|
3115
|
|
- re_socketout(re, i, "OK\n");
|
3116
|
|
-#if 1
|
|
3153
|
+#if 0
|
3117
|
3154
|
fprintf(stderr,"New client registered (%i).\n",i);
|
3118
|
3155
|
#endif
|
3119
|
3156
|
return(i);
|
...
|
...
|
@@ -3130,13 +3167,16 @@ int re_socketstep(re_t *re)
|
3130
|
3167
|
int avail,queued;
|
3131
|
3168
|
int nread,nwritten;
|
3132
|
3169
|
char *ptr,*next,*end;
|
3133
|
|
- if(re==NULL || re->comms.serverfd==-1)
|
|
3170
|
+ if(re==NULL)
|
3134
|
3171
|
return(-1); /* sanity check error */
|
3135
|
3172
|
comms=&(re->comms);
|
3136
|
3173
|
FD_ZERO(&readset);
|
3137
|
3174
|
FD_ZERO(&writeset);
|
3138
|
|
- maxfd=comms->serverfd;
|
3139
|
|
- FD_SET(comms->serverfd,&readset);
|
|
3175
|
+ maxfd=0;
|
|
3176
|
+ if(comms->serverfd!=-1) {
|
|
3177
|
+ maxfd=comms->serverfd;
|
|
3178
|
+ FD_SET(comms->serverfd,&readset);
|
|
3179
|
+ }
|
3140
|
3180
|
for(i=0;i<comms->sizeclients;i++) {
|
3141
|
3181
|
if((client=comms->clients[i])==NULL || client->fd==-1)
|
3142
|
3182
|
continue;
|
...
|
...
|
@@ -3158,8 +3198,8 @@ int re_socketstep(re_t *re)
|
3158
|
3198
|
if(select(maxfd+1,&readset,&writeset,NULL,&tv)<=0)
|
3159
|
3199
|
return(0); /* nothing to do */
|
3160
|
3200
|
/* server */
|
3161
|
|
- if(FD_ISSET(comms->serverfd,&readset))
|
3162
|
|
- re_socketnewclient(re);
|
|
3201
|
+ if(comms->serverfd!=-1 && FD_ISSET(comms->serverfd,&readset))
|
|
3202
|
+ re_socketnewclient(re,-1);
|
3163
|
3203
|
/* clients */
|
3164
|
3204
|
for(i=0;i<comms->sizeclients;i++) {
|
3165
|
3205
|
if((client=comms->clients[i])==NULL || client->fd==-1)
|
...
|
...
|
@@ -3167,16 +3207,20 @@ int re_socketstep(re_t *re)
|
3167
|
3207
|
if(FD_ISSET(client->fd,&readset)) {
|
3168
|
3208
|
if((queued=sock_queued(client->fd))<=0) {
|
3169
|
3209
|
/* remote has closed the connection */
|
3170
|
|
-#if 1
|
|
3210
|
+#if 0
|
3171
|
3211
|
fprintf(stderr,"Unregistering client, remote has closed the connection (%i).\n",i);
|
3172
|
3212
|
#endif
|
3173
|
3213
|
close(client->fd),client->fd=-1;
|
|
3214
|
+ if(client->flag_connectedtoserver) {
|
|
3215
|
+ client->flag_connectedtoserver=0;
|
|
3216
|
+ re_socketinit(re,re->filename);
|
|
3217
|
+ }
|
3174
|
3218
|
continue;
|
3175
|
3219
|
}
|
3176
|
3220
|
avail=(client->sizebufin-client->usedbufin);
|
3177
|
3221
|
queued=(queued>avail)?avail:queued;
|
3178
|
3222
|
if((nread=read(client->fd,client->bufin+client->usedbufin,queued))>0) {
|
3179
|
|
-#if 1
|
|
3223
|
+#if 0
|
3180
|
3224
|
fprintf(stderr,"Read from client %li bytes (%i).\n",(long)nread,i);
|
3181
|
3225
|
#endif
|
3182
|
3226
|
client->usedbufin+=nread;
|
...
|
...
|
@@ -3203,7 +3247,7 @@ fprintf(stderr,"Read from client %li bytes (%i).\n",(long)nread,i);
|
3203
|
3247
|
queued=client->usedbufout-client->gotbufout;
|
3204
|
3248
|
if((nwritten=write(client->fd,client->bufout+client->gotbufout,client->usedbufout-client->gotbufout))>0)
|
3205
|
3249
|
client->gotbufout+=nwritten;
|
3206
|
|
-#if 1
|
|
3250
|
+#if 0
|
3207
|
3251
|
fprintf(stderr,"Write to client %li bytes (%i).\n",(long)nwritten,i);
|
3208
|
3252
|
#endif
|
3209
|
3253
|
}
|
...
|
...
|
@@ -3217,14 +3261,23 @@ re_socketin(re_t *re, int nclient, char *line)
|
3217
|
3261
|
/* note that the '\n' delimiter has been already removed */
|
3218
|
3262
|
/* Commands can be sent from the command line using socat as in: */
|
3219
|
3263
|
/* "socat - UNIX-CONNECT:/tmp/.re_${USER}/filename.ext" */
|
|
3264
|
+ commclient_t *client;
|
3220
|
3265
|
char *ptr;
|
3221
|
|
-#if 1
|
|
3266
|
+ int i;
|
|
3267
|
+ if(re==NULL || nclient<0 || nclient>=re->comms.sizeclients || re->comms.clients[nclient]==NULL || line==NULL)
|
|
3268
|
+ return(-1); /* sanity check failed */
|
|
3269
|
+ client=re->comms.clients[nclient];
|
|
3270
|
+#if 0
|
3222
|
3271
|
fprintf(stderr,"Received from client \"%s\" (%i).\n",line,nclient);
|
3223
|
3272
|
#endif
|
3224
|
3273
|
if(memcmp(line,"goto ",5)==0) {
|
3225
|
3274
|
int oldline;
|
|
3275
|
+ int avail;
|
3226
|
3276
|
ptr=line+5;
|
3227
|
3277
|
/* change line */
|
|
3278
|
+#if 0
|
|
3279
|
+fprintf(stderr,"Changing line because of command from client \"%s\" (%i).\n",line,nclient);
|
|
3280
|
+#endif
|
3228
|
3281
|
re->command=COMMAND_GOTOLINE;
|
3229
|
3282
|
strncpy(re->commandbuf,ptr,sizeof(re->commandbuf));
|
3230
|
3283
|
re->commandbuf[sizeof(re->commandbuf)-1]='\0';
|
...
|
...
|
@@ -3237,6 +3290,33 @@ fprintf(stderr,"Received from client \"%s\" (%i).\n",line,nclient);
|
3237
|
3290
|
}
|
3238
|
3291
|
/* send end-of-results */
|
3239
|
3292
|
re_socketout(re, nclient, "\n");
|
|
3293
|
+ /* forward command to all identified clients except the one who sent teh command */
|
|
3294
|
+ for(i=0;i<re->comms.sizeclients;i++) {
|
|
3295
|
+#if 0
|
|
3296
|
+ if(re->comms.clients[i]!=NULL)
|
|
3297
|
+ fprintf(stderr,"Client[%i] id:\"%s\"\n",i,re->comms.clients[i]->remoteid);
|
|
3298
|
+#endif
|
|
3299
|
+ if(re->comms.clients[i]==NULL || re->comms.clients[i]->fd==-1 || re->comms.clients[i]->remoteid[0]=='\0')
|
|
3300
|
+ continue;
|
|
3301
|
+ avail=re->comms.clients[i]->sizebufout-re->comms.clients[i]->usedbufout;
|
|
3302
|
+ if((strlen(line)+1)>avail) {
|
|
3303
|
+ fprintf(stderr,"Couldn't forward command to client because the output buffer is full (avail:%li, req:%li)\n",(long)avail,(long)(strlen(line)+1));
|
|
3304
|
+ continue;
|
|
3305
|
+ }
|
|
3306
|
+ re_socketout(re, i, "%s\n",line);
|
|
3307
|
+ }
|
|
3308
|
+ } else if(memcmp(line,"id ",3)==0) {
|
|
3309
|
+ ptr=line+3;
|
|
3310
|
+ /* change id */
|
|
3311
|
+#if 0
|
|
3312
|
+fprintf(stderr,"Storing client id because of command from client \"%s\" (%i).\n",line,nclient);
|
|
3313
|
+#endif
|
|
3314
|
+ strncpy(client->remoteid,ptr,sizeof(client->remoteid));
|
|
3315
|
+ client->remoteid[sizeof(client->remoteid)-1]='\0';
|
|
3316
|
+ /* send end-of-results */
|
|
3317
|
+ re_socketout(re, nclient, "\n");
|
|
3318
|
+ } else if(line[0]=='\0' ) {
|
|
3319
|
+ ; /* ignore the end-of-message (should only receive them on forwarding clients) */
|
3240
|
3320
|
} else {
|
3241
|
3321
|
#if 1
|
3242
|
3322
|
fprintf(stderr,"Ignoring unknown command from client \"%s\" (%i).\n",line,nclient);
|