1 /*
2 LibRCC - rcc external is an application helper which is intended to execute
3 in a separate process code accessing glib library. This is necessary to be
4 able use translation services in RusXMMS patch. XMMS is dependent on Glib v.1
5 and libtranslate utilized to provide translation uses Glib v.2. If both
6 libraries are linked, the version conflict causes segmentation errors.
7
8 Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
9
10 This library is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License version 2.1 or later
12 as published by the Free Software Foundation.
13
14 This library is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17 for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28
29 #include "../config.h"
30
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif /* HAVE_UNISTD_H */
34
35 #ifdef HAVE_PWD_H
36 # include <pwd.h>
37 #endif /* HAVE_PWD_H */
38
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
41 #endif /* HAVE_SYS_TYPES_H */
42 #ifdef HAVE_SYS_SOCKET_H
43 # include <sys/socket.h>
44 #endif /* HAVE_SYS_SOCKET_H */
45 #ifdef HAVE_SYS_STAT_H
46 # include <sys/stat.h>
47 #endif /* HAVE_SYS_STAT_H */
48 #ifdef HAVE_SYS_UN_H
49 # include <sys/un.h>
50 #endif /* HAVE_SYS_UN_H */
51 #ifdef HAVE_SYS_TIME_H
52 # include <sys/time.h>
53 #endif /* JAVE_SYS_TIME_H */
54
55 #ifdef HAVE_SIGNAL_H
56 # include <signal.h>
57 #endif /* HAVE_SIGNAL_H */
58
59 #include <glib.h>
60
61 #include "../src/rcchome.h"
62 #include "../src/rccexternal.h"
63 #include "rcclibtranslate.h"
64
65 #include "compat.h"
66
67 #define RCC_EXIT_CHECK_TIMEOUT 10 /* seconds */
68
69
70 char rcc_external_offline = 0;
71
main()72 int main() {
73 #ifdef HAVE_SIGNAL_H
74 struct sigaction act;
75 #endif /* HAVE_PWD_H */
76 int err;
77 struct timeval tv;
78 fd_set fdcon;
79
80 int s, sd;
81 char addr[376];
82 struct sockaddr_un mysock, clisock;
83 socklen_t socksize;
84
85 pid_t parentpid;
86 pid_t mypid;
87
88 unsigned char loopflag = 1;
89
90 rcc_external_info info;
91 rcc_external_option option;
92 unsigned long option_value_long;
93
94 ssize_t readed;
95 unsigned char cmd;
96
97 parentpid = getppid();
98 mypid = getpid();
99
100 rccHomeSet();
101 rccLibTranslateInit(rcc_home_dir);
102
103 sprintf(addr,"%s/.rcc/comm/",rcc_home_dir);
104 mkdir(addr, 00700);
105 sprintf(addr,"%s/.rcc/comm/%lu.sock", rcc_home_dir, (unsigned long)mypid);
106
107 s = socket(PF_UNIX, SOCK_STREAM, 0);
108 if (!s) return -1;
109
110 memset(&mysock, 0, sizeof(mysock));
111 mysock.sun_family=AF_UNIX;
112 strncpy(mysock.sun_path,addr,sizeof(mysock.sun_path));
113 mysock.sun_path[sizeof(mysock.sun_path)-1]=0;
114
115 unlink(addr);
116
117 if (bind(s,(struct sockaddr*)&mysock,sizeof(mysock))==-1) return -1;
118 if (listen(s,1)<0) {
119 unlink(addr);
120 return -1;
121 }
122
123 #ifdef HAVE_SIGNAL_H
124 act.sa_handler = SIG_IGN;
125 sigemptyset(&act.sa_mask);
126 act.sa_flags = 0;
127 sigaction(SIGPIPE,&act,NULL);
128 sigaction(SIGINT,&act,NULL);
129 #endif /* HAVE_SIGNAL_H */
130
131 while (loopflag) {
132 tv.tv_sec = RCC_EXIT_CHECK_TIMEOUT;
133 tv.tv_usec = 0;
134
135 FD_ZERO(&fdcon);
136 FD_SET(s, &fdcon);
137
138 err = select(s+1, &fdcon, NULL, NULL, &tv);
139 if (err<=0) {
140 if (getppid() != parentpid) break;
141 continue;
142 }
143
144 sd = accept(s,(struct sockaddr*)&clisock,&socksize);
145 if (sd < 0) continue;
146
147 readed = recv(sd,&cmd,1,0);
148 if (readed<=0) {
149 close(sd);
150 continue;
151 }
152
153 switch (cmd) {
154 case RCC_EXTERNAL_MODULE_CONTROL:
155 loopflag = 0;
156 break;
157 case RCC_EXTERNAL_MODULE_OPTIONS:
158 readed = recv(sd,&option,sizeof(rcc_external_option),0);
159 if (readed < sizeof(rcc_external_option)) break;
160 switch(option) {
161 case RCC_EXTERNAL_OPTION_OFFLINE:
162 readed = recv (sd, &option_value_long, sizeof(unsigned long), 0);
163 if (readed < sizeof(unsigned long)) break;
164 puts("got an offline option");
165 rcc_external_offline = option_value_long?1:0;
166 break;
167 default:
168 break;
169 }
170 break;
171 case RCC_EXTERNAL_MODULE_LIBRTRANSLATE:
172 info = (rcc_external_info)malloc(sizeof(rcc_external_info_s));
173 if (info) info->s = sd;
174 else break;
175 if (g_thread_create_compat(rccLibTranslate, info, FALSE)) continue;
176 break;
177 }
178 close(sd);
179 }
180
181 close(s);
182 unlink(addr);
183
184 rccLibTranslateFree();
185 rccHomeFree();
186
187 return 0;
188 }
189