1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <stdio.h>
8 
9 typedef struct {
10   char* filename; /* this file is the pipe (set by user) */
11   char is_server; /* this is set by open_control_file */
12   int fd; /* this is set by open_control_file */
13 } single_instance_struct;
14 
15 /* returns fd, is_server is set to -1 if server, 0 if client */
open_control_file(single_instance_struct * str)16 int open_control_file(single_instance_struct* str)
17 {
18   struct stat buf;
19 
20   if(stat(str->filename,&buf)) {
21     mkfifo(str->filename,128|256);
22     str->is_server=-1;
23     str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
24   } else {
25     str->fd=open(str->filename,O_NONBLOCK|O_WRONLY);
26     if(errno==ENXIO) {
27       str->is_server=-1;
28       str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
29     } else
30       str->is_server=0;
31   }
32 
33   return(str->fd);
34 }
35 
delete_control_file(single_instance_struct * str)36 void delete_control_file(single_instance_struct* str)
37 {
38   remove(str->filename);
39 }
40 
close_control_file(single_instance_struct * str)41 void close_control_file(single_instance_struct* str)
42 {
43   close(str->fd);
44 }
45 
46 typedef void (*event_dispatcher)(char* message);
47 
get_next_message(char * buffer,int len,single_instance_struct * str,int usecs)48 int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
49 {
50   struct timeval tv;
51   fd_set fdset;
52   int num_fds;
53 
54   FD_ZERO(&fdset);
55   FD_SET(str->fd,&fdset);
56   tv.tv_sec=0;
57   tv.tv_usec=usecs;
58 
59   num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv);
60   if(num_fds) {
61     int reallen;
62 
63     reallen=read(str->fd,buffer,len);
64     if(reallen==0) {
65       close(str->fd);
66       str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
67       num_fds--;
68     }
69     buffer[reallen]=0;
70 #ifdef DEBUG_1INSTANCE
71     if(reallen!=0) rfbLog("message received: %s.\n",buffer);
72 #endif
73   }
74 
75   return(num_fds);
76 }
77 
dispatch_event(single_instance_struct * str,event_dispatcher dispatcher,int usecs)78 int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
79 {
80   char buffer[1024];
81   int num_fds;
82 
83   if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0])
84     dispatcher(buffer);
85 
86   return(num_fds);
87 }
88 
loop_if_server(single_instance_struct * str,event_dispatcher dispatcher)89 int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
90 {
91   open_control_file(str);
92   if(str->is_server) {
93     while(1)
94       dispatch_event(str,dispatcher,50);
95   }
96 
97   return(str->fd);
98 }
99 
send_message(single_instance_struct * str,char * message)100 void send_message(single_instance_struct* str,char* message)
101 {
102 #ifdef DEBUG_1INSTANCE
103   int i=
104 #endif
105   write(str->fd,message,strlen(message));
106 #ifdef DEBUG_1INSTANCE
107   rfbLog("send: %s => %d(%d)\n",message,i,strlen(message));
108 #endif
109 }
110 
111 #ifdef DEBUG_MAIN
112 
113 #include <stdio.h>
114 #include <stdlib.h>
115 
116 single_instance_struct str1 = { "/tmp/1instance" };
117 
my_dispatcher(char * message)118 void my_dispatcher(char* message)
119 {
120 #ifdef DEBUG_1INSTANCE
121   rfbLog("Message arrived: %s.\n",message);
122 #endif
123   if(!strcmp(message,"quit")) {
124     delete_control_file(str1);
125     exit(0);
126   }
127 }
128 
main(int argc,char ** argv)129 int main(int argc,char** argv)
130 {
131   int i;
132 
133   loop_if_server(str1,my_dispatcher);
134 
135   for(i=1;i<argc;i++)
136     send_event(str1,argv[i]);
137 
138   return(0);
139 }
140 
141 #endif
142