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