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