Initialize Tizen 2.3
[framework/system/deviced.git] / src / core / sysnoti.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 #include <limits.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/stat.h>
25 #include "data.h"
26 #include "log.h"
27 #include "queue.h"
28 #include "common.h"
29 #include "devices.h"
30
31 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
32 #define RETRY_READ_COUNT        5
33 enum sysnoti_cmd {
34         REGISTER_MSG,
35         NOTIFY_MSG
36 };
37
38 static Ecore_Fd_Handler *sysnoti_efd = NULL;
39 static int sysnoti_fd;
40 static int __sysnoti_start(void);
41 static int __sysnoti_stop(int fd);
42
43 static void print_sysnoti_msg(const char *title, struct sysnoti *msg)
44 {
45         int i;
46         char exe_name[PATH_MAX];
47
48         if (get_cmdline_name(msg->pid, exe_name, PATH_MAX) < 0)
49                 snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)");
50
51         _SD("pid : %d name: %s cmd : %d type : %s path : %s",
52                         msg->pid, exe_name, msg->cmd, msg->type, msg->path);
53 }
54
55 static inline int recv_int(int fd)
56 {
57         int val, r = -1;
58         int retry_count = 0;
59         while (retry_count < RETRY_READ_COUNT) {
60                 r = read(fd, &val, sizeof(int));
61                 if (r < 0) {
62                         if(errno == EINTR) {
63                                 _D("Re-read for error(EINTR)");
64                                 retry_count++;
65                                 continue;
66                         }
67                         else {
68                                 _E("Read fail for int");
69                                 return -1;
70                         }
71                 } else {
72                         return val;
73                 }
74         }
75         return -1;
76 }
77
78 static inline char *recv_str(int fd)
79 {
80         int len, r = -1;
81         int retry_count = 0;
82         char *str;
83
84         while (retry_count < RETRY_READ_COUNT) {
85                 r = read(fd, &len, sizeof(int));
86                 if (r < 0) {
87                         if(errno == EINTR) {
88                                 _D("Re-read for error(EINTR)");
89                                 retry_count++;
90                                 continue;
91                         }
92                         else {
93                                 _E("Read fail for str length");
94                                 return NULL;
95                         }
96                 } else
97                         break;
98         }
99         if (retry_count == RETRY_READ_COUNT) {
100                 _E("Read retry failed");
101                 return NULL;
102         }
103         if (len <= 0)
104                 return NULL;
105
106         if (len >= INT_MAX) {
107                 _E("size is over INT_MAX");
108                 return NULL;
109         }
110
111         str = (char *)malloc(len + 1);
112         if (str == NULL) {
113                 _E("Not enough memory");
114                 return NULL;
115         }
116         retry_count = 0;
117         while (retry_count < RETRY_READ_COUNT) {
118                 r = read(fd, str, len);
119                 if(r < 0) {
120                         if(errno == EINTR) {
121                                 _D("Re-read for error(EINTR)");
122                                 retry_count++;
123                                 continue;
124                         } else {
125                                 _E("Read fail for str");
126                                 free(str);
127                                 str = NULL;
128                                 return NULL;
129                         }
130                 } else
131                         break;
132         }
133         if (retry_count == RETRY_READ_COUNT) {
134                 _E("Read retry failed");
135                 free(str);
136                 str = NULL;
137                 return NULL;
138         }
139
140         str[len] = 0;
141         return str;
142 }
143
144 static int read_message(int fd, struct sysnoti *msg)
145 {
146         int i;
147
148         if ((msg->pid = recv_int(fd)) == -1)
149                 return -1;
150         if ((msg->cmd = recv_int(fd)) == -1)
151                 return -1;
152         if ((msg->type = recv_str(fd)) == NULL)
153                 return -1;
154         msg->path = recv_str(fd);
155         msg->argc = recv_int(fd);
156
157         if (msg->argc < 0)
158                 return -1;
159         for (i = 0; i < msg->argc; i++)
160                 msg->argv[i] = recv_str(fd);
161
162         return 0;
163 }
164
165 static inline void internal_free(char *str)
166 {
167         if (str)
168                 free(str);
169 }
170
171 static inline void free_message(struct sysnoti *msg)
172 {
173         internal_free(msg->type);
174         internal_free(msg->path);
175         free(msg);
176 }
177
178 static Eina_Bool sysnoti_cb(void *data, Ecore_Fd_Handler * fd_handler)
179 {
180         struct sysnoti *msg;
181         int ret = -1;
182         struct sockaddr_un client_address;
183         int client_sockfd;
184         int client_len;
185
186         if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
187                 _E("ecore_main_fd_handler_active_get error , return");
188                 goto out;
189         }
190
191         msg = malloc(sizeof(struct sysnoti));
192         if (msg == NULL) {
193                 _E("Not enough memory");
194                 goto out;
195         }
196
197         client_len = sizeof(client_address);
198         client_sockfd = accept(sysnoti_fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
199
200         if (client_sockfd == -1) {
201                 _E("socket accept error");
202                 free(msg);
203                 goto out;
204         }
205         if (read_message(client_sockfd, msg) < 0) {
206                 _E("recv error msg");
207                 print_sysnoti_msg(__FUNCTION__, msg);
208                 free_message(msg);
209                 write(client_sockfd, &ret, sizeof(int));
210                 close(client_sockfd);
211                 __sysnoti_stop(sysnoti_fd);
212                 __sysnoti_start();
213                 goto out;
214         }
215
216         print_sysnoti_msg(__FUNCTION__, msg);
217         if (msg->argc > SYSMAN_MAXARG) {
218                 _E("error argument");
219                 free_message(msg);
220                 write(client_sockfd, &ret, sizeof(int));
221                 close(client_sockfd);
222                 goto out;
223         }
224
225         switch (msg->cmd) {
226 #ifdef NOUSE
227         case REGISTER_MSG:
228                 ret = register_msg(msg);
229                 _E("%d", ret);
230                 break;
231 #endif
232         case NOTIFY_MSG:
233                 ret = notify_msg(msg, client_sockfd);
234                 break;
235         default:
236                 ret = -1;
237         }
238
239
240         write(client_sockfd, &ret, sizeof(int));
241         close(client_sockfd);
242
243         free_message(msg);
244 out:
245         return EINA_TRUE;
246 }
247
248 static int sysnoti_server_init(void)
249 {
250         int fd;
251         struct sockaddr_un serveraddr;
252
253         if (access(SYSNOTI_SOCKET_PATH, F_OK) == 0)
254                 unlink(SYSNOTI_SOCKET_PATH);
255
256         fd = socket(AF_UNIX, SOCK_STREAM, 0);
257         if (fd < 0) {
258                 _E("socket create failed");
259                 return -1;
260         }
261         if((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0 ) {
262                 _E("Socket SMACK labeling failed");
263                 if(errno != EOPNOTSUPP) {
264                         close(fd);
265                         return -1;
266                 }
267         }
268
269         if((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0 ) {
270                 _E("Socket SMACK labeling failed");
271                 if(errno != EOPNOTSUPP) {
272                         close(fd);
273                         return -1;
274                 }
275         }
276
277         bzero(&serveraddr, sizeof(struct sockaddr_un));
278         serveraddr.sun_family = AF_UNIX;
279         strncpy(serveraddr.sun_path, SYSNOTI_SOCKET_PATH,
280                 sizeof(serveraddr.sun_path));
281
282         if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) < 0) {
283                 _E("socket bind failed");
284                 close(fd);
285                 return -1;
286         }
287
288         if (chmod(SYSNOTI_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)      /* 0777 */
289                 _E("failed to change the socket permission");
290
291         if (listen(fd, 5) < 0) {
292                 _E("failed to listen");
293                 close(fd);
294                 return -1;
295         }
296
297         return fd;
298 }
299
300 static int __sysnoti_start(void)
301 {
302         sysnoti_fd = sysnoti_server_init();
303         if ( sysnoti_fd < 0 )
304                 return -1;
305         sysnoti_efd = ecore_main_fd_handler_add(sysnoti_fd, ECORE_FD_READ, sysnoti_cb, NULL, NULL,
306                                   NULL);
307         if (!sysnoti_efd) {
308                 _E("error ecore_main_fd_handler_add");
309                 close(sysnoti_fd);
310                 return -1;
311         }
312         return 0;
313 }
314
315 static int __sysnoti_stop(int fd)
316 {
317         if (sysnoti_efd) {
318                 ecore_main_fd_handler_del(sysnoti_efd);
319                 sysnoti_efd = NULL;
320         }
321         if (fd >=0) {
322                 close(fd);
323                 fd = -1;
324         }
325         return 0;
326 }
327
328 static void sysnoti_init(void *data)
329 {
330         struct main_data *ad = (struct main_data*)data;
331
332         if (__sysnoti_start() == -1)
333                 _E("fail sys socket fd init");
334 }
335
336 static const struct device_ops sysnoti_device_ops = {
337         .priority = DEVICE_PRIORITY_NORMAL,
338         .name     = "sysnoti",
339         .init     = sysnoti_init,
340 };
341
342 DEVICE_OPS_REGISTER(&sysnoti_device_ops)