1 //  MaCoPiX = Mascot Construnctive Pilot for X
2 //                                (ActX / Gtk+ Evolution)
3 //
4 //
5 //      sockmsg.c
6 //      Management of Socket message function
7 //
8 //                            Copyright 2002-2008  K.Chimari
9 //                                     http://rosegray.sakura.ne.jp/
10 //
11 //
12 //  This program is free software; you can redistribute it and/or modify
13 //  it under the terms of the GNU General Public License as published by
14 //  the Free Software Foundation; either version 2 of the License, or
15 //  (at your option) any later version.
16 //
17 //  This program is distributed in the hope that it will be useful,
18 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 //  GNU General Public License for more details.
21 //
22 //  You should have received a copy of the GNU General Public License
23 //  along with this program; if not, write to the Free Software
24 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
25 //
26 
27 #include "main.h"
28 
29 #ifdef USE_SOCKMSG
30 
31 #include <glib.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <sys/un.h>
36 #include <netdb.h>
37 #include <ctype.h>
38 
39 #include "sockmsg.h"
40 
41 extern gboolean flag_balloon;
42 
43 gchar *cut_spc(gchar * obj_name);
44 static gchar *get_socket_name(void);
45 static gchar *get_duet_name(gchar *mascotname);
46 static gint fd_open_unix(const gchar *path);
47 static gint fd_connect_unix(const gchar *path);
48 static gint fd_accept(gint sock);
49 static gint fd_close(gint fd);
50 static gboolean io_callback(GIOChannel * source,
51 			    GIOCondition condition, gpointer data);
52 static gboolean io_callback_sv(GIOChannel * source,
53 			       GIOCondition condition, gpointer data);
54 SockMsgInitResult sockmsg_init(void);
55 SockMsgInitResult duet_sv_init(gchar *mascotname);
56 SockMsgInitResult duet_cl_init(gchar *mascotname);
57 void sockmsg_set_mascot(typMascot *mascot);
58 void duet_set_mascot(typMascot *mascot);
59 void sockmsg_send_msg(gchar *msg);
60 void duet_send_msg(gchar *msg);
61 void sockmsg_done(void);
62 void duet_sv_done(gchar *mascotname, gboolean flag_close);
63 void duet_cl_done(gchar *mascotname, gboolean flag_close);
64 #ifdef USE_GTK2
65 gchar* set_typing_msg();
66 gchar* my_strbuf();
67 #endif //USE_GTK2
68 
69 
cut_spc(gchar * obj_name)70 gchar *cut_spc(gchar * obj_name){
71   gchar *tgt_name=NULL, *ret_name, *c;
72   gint  i_bak,i;
73 
74   tgt_name=g_strdup(obj_name);
75   i_bak=strlen(tgt_name)-1;
76   while((tgt_name[i_bak]==0x20)
77         ||(tgt_name[i_bak]==0x0A)
78         ||(tgt_name[i_bak]==0x0D)
79         ||(tgt_name[i_bak]==0x09)){
80     //tgt_name[i_bak]=(char)NULL;
81     tgt_name[i_bak]=0x00;
82     i_bak--;
83   }
84 
85   c=tgt_name;
86   i=0;
87   while((tgt_name[i]==0x20)||(tgt_name[i]==0x09)){
88     c++;
89     i++;
90   }
91 
92   return(tgt_name);
93 }
94 
95 
get_socket_name(void)96 static gchar *get_socket_name(void)
97 {
98   static gchar *filename = NULL;
99   gchar *dirname = NULL;
100 
101   dirname = g_strdup_printf("%s%cmacopix-%d",
102 			    g_get_tmp_dir(), G_DIR_SEPARATOR, getuid());
103   if (access(dirname, F_OK) != 0) {
104     mkdir(dirname,(S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH));
105   }
106   g_free(dirname);
107 
108   if (filename == NULL) {
109     filename = g_strdup_printf("%s%cmacopix-%d%cmacopix",
110 			       g_get_tmp_dir(), G_DIR_SEPARATOR,
111 			       getuid(), G_DIR_SEPARATOR);
112   }
113 
114   return filename;
115 }
116 
get_duet_name(gchar * mascotname)117 static gchar *get_duet_name(gchar *mascotname)
118 {
119   static gchar *filename = NULL;
120   gchar *dirname = NULL;
121 
122   dirname = g_strdup_printf("%s%cmacopix-%d",
123 			    g_get_tmp_dir(), G_DIR_SEPARATOR, getuid());
124   if (access(dirname, F_OK) != 0) {
125     mkdir(dirname,(S_IRWXU|S_IRGRP|S_IROTH|S_IRGRP|S_IROTH));
126   }
127   g_free(dirname);
128 
129   filename = g_strdup_printf("%s%cmacopix-%d%cmacopix-%s",
130 			     g_get_tmp_dir(),
131 			     G_DIR_SEPARATOR,
132 			     getuid(),
133 			     G_DIR_SEPARATOR,
134 			     mascotname);
135 
136   return filename;
137 }
138 
fd_open_unix(const gchar * path)139 static gint fd_open_unix(const gchar *path)
140 {
141 	gint sock;
142 	struct sockaddr_un addr;
143 
144 	sock = socket(PF_UNIX, SOCK_STREAM, 0);
145 
146 	if (sock < 0) {
147 		perror("sock_open_unix(): socket");
148 		return -1;
149 	}
150 
151 	memset(&addr, 0, sizeof(addr));
152 	addr.sun_family = AF_UNIX;
153 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
154 
155 	if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
156 		perror("bind");
157 		close(sock);
158 		return -1;
159 	}
160 
161 	if (listen(sock, 1) < 0) {
162 		perror("listen");
163 		close(sock);
164 		return -1;
165 	}
166 
167 	return sock;
168 }
169 
fd_connect_unix(const gchar * path)170 static gint fd_connect_unix(const gchar *path)
171 {
172 	gint sock;
173 	struct sockaddr_un addr;
174 
175 	sock = socket(PF_UNIX, SOCK_STREAM, 0);
176 	if (sock < 0) {
177 		perror("sock_connect_unix(): socket");
178 		return -1;
179 	}
180 
181 	memset(&addr, 0, sizeof(addr));
182 	addr.sun_family = AF_UNIX;
183 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
184 
185 	if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
186 		close(sock);
187 		return -1;
188 	}
189 
190 	return sock;
191 }
192 
fd_accept(gint sock)193 static gint fd_accept(gint sock)
194 {
195 	struct sockaddr_in caddr;
196 	gint caddr_len;
197 
198 	caddr_len = sizeof(caddr);
199 	return accept(sock, (struct sockaddr *)&caddr, &caddr_len);
200 }
201 
fd_close(gint fd)202 static gint fd_close(gint fd)
203 {
204 	return close(fd);
205 }
206 
io_callback(GIOChannel * source,GIOCondition condition,gpointer data)207 static gboolean io_callback(GIOChannel * source,
208 		  GIOCondition condition, gpointer data)
209 {
210   gchar buf[2048],tmp[10];
211 	gint fd, readsize;
212 	typMascot *mascot = data;
213 	gint step,mode;
214 
215 	fd = fd_accept(g_io_channel_unix_get_fd(source));
216 
217 	readsize = read(fd, buf, 2047);
218 	buf[readsize] = '\0';
219 
220 	fd_close(fd);
221 
222 	// Expiration
223 	strncpy(tmp,buf,8);
224 	mascot->sockmsg_expire=(gint)(atoi(tmp)/INTERVAL);
225 	if(mascot->sockmsg_expire<=0){
226 	  mascot->sockmsg_expire=mascot->sockmsg_expire_def/INTERVAL;
227 	}
228 
229 	// Stepping or Lump Sum?
230 	strncpy(tmp,buf+8,2);
231 	mode=(gint)atoi(tmp);
232 	if(mode<0){
233 	  mode=mascot->sockmsg_type;
234 	}
235 
236 	// Stepping Interval
237 	strncpy(tmp,buf+8+2,4);
238 	step=(gint)atoi(tmp);
239 	if(step<0){
240 	  step=mascot->sockmsg_step;
241 	}
242 
243 
244 	mascot->balseq=0;
245 	mascot->bal_mode=BALLOON_SOCKMSG;
246 	if (mascot->sockmsg != NULL)
247 		g_free(mascot->sockmsg);
248 #ifdef USE_GTK2
249 	if(mode==SOCK_STEPPING){
250 	  mascot->sockmsg = set_typing_msg(buf+8+2+4,step);
251 	}
252 	else{
253 	  mascot->sockmsg = g_strdup(buf+8+2+4);
254 	}
255 #else
256 	mascot->sockmsg = g_strdup(buf+8+2+4);
257 #endif
258 	DoBalloon(mascot);
259 	flag_balloon=TRUE;
260 
261 }
262 
io_callback_sv(GIOChannel * source,GIOCondition condition,gpointer data)263 static gboolean io_callback_sv(GIOChannel * source,
264 		  GIOCondition condition, gpointer data)
265 {
266 	gchar buf[2048],tmp[8];
267 	gint fd, readsize;
268 	typMascot *mascot = data;
269 	gint i_ptn,i_frm;
270 	gint mode;
271 
272 	fd = fd_accept(g_io_channel_unix_get_fd(source));
273 
274 	readsize = read(fd, buf, 2047);
275 	buf[readsize] = '\0';
276 
277 	fd_close(fd);
278 
279 	if(readsize<4) return(0);
280 
281 	strncpy(tmp,buf,2);
282 	mode=atoi(tmp);
283 	strncpy(tmp,buf+2,2);
284 	i_ptn=atoi(tmp);
285 
286 	if(mode==DUET_CLICK){
287 	  if (mascot->sockmsg != NULL)
288 	    g_free(mascot->sockmsg);
289 	  mascot->sockmsg=g_strdup(buf+2+2);
290 	}
291 
292 
293 	// ����å����˥�
294 	if((mode==DUET_CLICK)&&(mascot->duet_use_click)){
295 	  if(mascot->frame_pix[i_ptn][0]!=-1){
296 	    for(i_frm=0;i_frm<mascot->frame_num[mascot->anime_ptn];i_frm++){
297 	      // �֥�å��롼�פΥ������
298 	      mascot->frame_loop[mascot->anime_ptn][i_frm].seq=0;
299 	    }
300 	    //mascot->anime_ptn=weight_click(mascot);
301 	    mascot->anime_ptn=i_ptn;
302 	    mascot->anime_frm=-1;
303 	    mascot->anime_seq=-1;
304 	    mascot->anime_seqend=
305 	      RANDOM(mascot->frame_max[mascot->anime_ptn][mascot->anime_frm]
306 		     -mascot->frame_min[mascot->anime_ptn][mascot->anime_frm]+1)
307 	      +mascot->frame_min[mascot->anime_ptn][mascot->anime_frm];
308 
309 	    sound_play(mascot,mascot->click_sound[mascot->anime_ptn]);
310 
311 	    if(mascot->sockmsg){
312 	      if(strlen(mascot->sockmsg)>0){
313 		mascot->balseq=0;
314 		mascot->bal_mode=BALLOON_DUET;
315 		DoBalloon(mascot);
316 		flag_balloon=TRUE;
317 	      }
318 	    }
319 	  }
320 	}
321 	else if (mascot->duet_use_random){
322 	  if(mascot->anime_ptn==0){ // �����ॢ�˥�
323 	    if(mascot->frame_pix[i_ptn][0]!=-1){
324 	      mascot->anime_ptn=i_ptn;
325 	      mascot->anime_frm=0;
326 	    }
327 	  }
328 	}
329 }
330 
331 
332 gint sock = -1;
333 gint io_watch = -1;
334 
sockmsg_init()335 SockMsgInitResult sockmsg_init() {
336 	gchar *sockname;
337 	SockMsgInitResult result;
338 
339 	sockname = get_socket_name();
340 
341 	sock = fd_connect_unix(sockname);
342 	if (sock < 0) {
343 		unlink(sockname);
344 		sock = fd_open_unix(sockname);
345 		if (sock < 0)
346 			result = SOCKMSG_ERROR;
347 		else
348 			result = SOCKMSG_CREATED;
349 	} else {
350 		result = SOCKMSG_OPENED;
351 	}
352 
353 	return result;
354 }
355 
356 gint duet_sv = -1;
357 gint io_watch_sv = -1;
358 
duet_sv_init(gchar * mascotname)359 SockMsgInitResult duet_sv_init(gchar *mascotname) {
360   gchar *sockname;
361   SockMsgInitResult result;
362 
363   sockname = get_duet_name(mascotname);
364 
365   duet_sv = fd_connect_unix(sockname);
366   if (duet_sv < 0) {
367     unlink(sockname);
368     duet_sv = fd_open_unix(sockname);
369     if (duet_sv < 0){
370       //fd_close(duet_sv);
371       result = SOCKMSG_ERROR;
372     }
373     else
374       result = SOCKMSG_CREATED;
375   } else {
376     // Already Opened / Close���ƺƥ����ץ��롣
377     fd_close(duet_sv);
378     unlink(sockname);
379     duet_sv = fd_open_unix(sockname);
380     result = SOCKMSG_OPENED;
381   }
382 
383   return result;
384 }
385 
386 gint duet_cl = -1;
387 
duet_cl_init(gchar * mascotname)388 SockMsgInitResult duet_cl_init(gchar *mascotname) {
389   gchar *sockname;
390   SockMsgInitResult result;
391 
392   sockname = get_duet_name(mascotname);
393 
394   duet_cl = fd_connect_unix(sockname);
395   if (duet_cl < 0) {
396     //fd_close(duet_cl);
397     result = SOCKMSG_ERROR;
398   } else {
399     result = SOCKMSG_OPENED;
400   }
401 
402   return result;
403 }
404 
sockmsg_set_mascot(typMascot * mascot)405 void sockmsg_set_mascot(typMascot *mascot)
406 {
407 	GIOChannel *io;
408 
409 	io = g_io_channel_unix_new(sock);
410 	io_watch = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_PRI, io_callback, mascot);
411 	g_io_channel_unref(io);
412 }
413 
duet_set_mascot(typMascot * mascot)414 void duet_set_mascot(typMascot *mascot)
415 {
416 	GIOChannel *io;
417 
418 	io = g_io_channel_unix_new(duet_sv);
419 	io_watch_sv = g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_PRI, io_callback_sv, mascot);
420 	g_io_channel_unref(io);
421 }
422 
sockmsg_send_msg(gchar * msg)423 void sockmsg_send_msg(gchar *msg)
424 {
425 #ifdef USE_GTK2
426         msg = g_locale_to_utf8(msg,-1,NULL,NULL,NULL);
427         if(!msg)
428     		_("(Invalid Character Code)");
429 #endif
430 
431 	if (write(sock, msg, strlen(msg)) <0){
432 	  printf("Error : sockmsg_send_msg();\n");
433 	  return;
434 	}
435 }
436 
duet_send_msg(gchar * msg)437 void duet_send_msg(gchar *msg)
438 {
439 #ifdef USE_GTK2
440         msg = g_locale_to_utf8(msg,-1,NULL,NULL,NULL);
441         if(!msg)
442     		_("(Invalid Character Code)");
443 #endif
444 
445 	if (write(duet_cl, msg, strlen(msg)) <0){
446 	  printf("Error : duet_send_msg();\n");
447 	  return;
448 	}
449 
450 }
451 
sockmsg_done()452 void sockmsg_done()
453 {
454 	gchar *sockname;
455 
456 	if (io_watch != -1)
457 		g_source_remove(io_watch);
458         fd_close(sock);
459 
460         sockname = get_socket_name();
461         unlink(sockname);
462 }
463 
duet_sv_done(gchar * mascotname,gboolean flag_close)464 void duet_sv_done(gchar *mascotname, gboolean flag_close)
465 {
466 	gchar *sockname;
467 
468 	if (io_watch_sv != -1)
469 		g_source_remove(io_watch_sv);
470         fd_close(duet_sv);
471 
472 	if(flag_close) {
473 	  sockname = get_duet_name(mascotname);
474 	  unlink(sockname);
475 	}
476 }
477 
duet_cl_done(gchar * mascotname,gboolean flag_close)478 void duet_cl_done(gchar *mascotname, gboolean flag_close)
479 {
480 	gchar *sockname;
481 
482         fd_close(duet_cl);
483 
484 	if(flag_close) {
485 	  sockname = get_duet_name(mascotname);
486 	  unlink(sockname);
487 	}
488 }
489 
490 #ifdef USE_GTK2
set_typing_msg(gchar * input,gint interval)491 gchar* set_typing_msg(gchar* input, gint interval){
492   gchar *p, *p1, *ret;
493   gint i,j,num;
494 
495   p = input;
496   ret=my_strbuf(NULL);
497 
498   while (*p) {
499     gunichar ch, ch1;
500     gchar tmp[64];
501 
502     ch= g_utf8_get_char (p);
503 
504     if (ch == '%'){
505       num=0;
506       i=0;
507       p1=p;
508       for(;;){
509 	p1=g_utf8_next_char (p1);
510 	ch1= g_utf8_get_char (p1);
511 	if((ch1 == 'c')||(ch1 == 'a')||(ch1 == 'n')||(ch1 == 'p')){
512 	  i++;
513 	  break;
514 	}
515 	else if(isdigit(ch1)){
516 	  i++;
517 	}
518 	else{
519 	  i=0;
520 	  break;
521 	}
522       }
523 
524       if(i!=0){
525 	ret=my_strbuf("%");
526 	for(j=0;j<i;j++){
527 	  p = g_utf8_next_char (p);
528 	  g_utf8_strncpy(tmp,p,1);
529 	  ret=my_strbuf(tmp);
530 	}
531       }
532       else{
533 	sprintf(tmp,"%%%%%%%dc",interval);
534 	ret=my_strbuf(tmp);
535       }
536     }
537     else{
538       g_utf8_strncpy(tmp,p,1);
539       ret=my_strbuf(tmp);
540       sprintf(tmp,"%%%dc",interval);
541       ret=my_strbuf(tmp);
542     }
543 
544 
545     p = g_utf8_next_char (p);
546   }
547   //fprintf(stderr,"%s\n",ret);
548   //fflush(stderr);
549 
550   return(ret);
551 }
552 
my_strbuf(gchar * p)553 gchar* my_strbuf(gchar *p)
554 {
555   static gchar    *start = NULL;
556   static gchar    *next;
557   static int      len, len2, l;
558 
559   if (p == NULL) {
560     len = len2 = 4096;
561     start = next = (gchar *) g_malloc(len + 1);
562     start[0] = '\0';
563   } else if (start != NULL) {
564     l = strlen(p);
565     while (len - l < 0) {
566       gchar           *p;
567       len2 += 256;
568       len += 256;
569       p = (gchar *) g_realloc(start, len2 + 1);
570       start = p;
571       next = p + len2 - len;
572                 }
573     strcpy(next,p);
574     len -= l;
575     next += l;
576   }
577   return start;
578 }
579 #endif //USE_GTK2
580 
581 #endif  // USE_SOCKMSG
582 
583