apply FSL(Flora Software License)
[framework/system/system-server.git] / ss_sysnoti.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17
18 #include <sysman.h>
19 #include <limits.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <sys/stat.h>
24 #include "include/ss_data.h"
25 #include "ss_log.h"
26 #include "ss_queue.h"
27
28 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
29
30 enum sysnoti_cmd {
31         ADD_SYSMAN_ACTION,
32         CALL_SYSMAN_ACTION
33 };
34
35 static void print_sysnoti_msg(const char *title, struct sysnoti *msg)
36 {
37         int i;
38         char exe_name[PATH_MAX];
39
40         if (sysman_get_cmdline_name(msg->pid, exe_name, PATH_MAX) < 0)
41                 snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)");
42
43         PRT_TRACE_ERR("=====================");
44         PRT_TRACE_ERR("pid : %d", msg->pid);
45         PRT_TRACE_ERR("process name : %s", exe_name);
46         PRT_TRACE_ERR("cmd : %d", msg->cmd);
47         PRT_TRACE_ERR("type : %s", msg->type);
48         PRT_TRACE_ERR("path : %s", msg->path);
49         for (i = 0; i < msg->argc; i++)
50                 PRT_TRACE_ERR("arg%d : %s", i, msg->argv[i]);
51         PRT_TRACE_ERR("=====================");
52 }
53
54 static inline int recv_int(int fd)
55 {
56         int val, r = -1;
57         while(1) {
58                 r = read(fd, &val, sizeof(int));
59                 if (r < 0) {
60                         if(errno == EINTR) {
61                                 PRT_TRACE_ERR("Re-read for error(EINTR)");
62                                 continue;
63                         }
64                         else {
65                                 PRT_TRACE_ERR("Read fail for int");
66                                 return -1;
67                         }
68                 } else {
69                         return val;
70                 }
71         }
72 }
73
74 static inline char *recv_str(int fd)
75 {
76         int len, r = -1;
77         char *str;
78
79         while(1) {
80                 r = read(fd, &len, sizeof(int));
81                 if (r < 0) {
82                         if(errno == EINTR) {
83                                 PRT_TRACE_ERR("Re-read for error(EINTR)");
84                                 continue;
85                         }
86                         else {
87                                 PRT_TRACE_ERR("Read fail for str length");
88                                 return NULL;
89                         }
90                 } else
91                         break;
92         }
93
94         if (len <= 0) {
95                 PRT_TRACE_ERR("str is null");
96                 return NULL;
97         }
98
99         if (len >= INT_MAX) {
100                 PRT_TRACE_ERR("size is over INT_MAX");
101                 return NULL;
102         }
103
104         str = (char *)malloc(len + 1);
105         if (str == NULL) {
106                 PRT_TRACE_ERR("Not enough memory");
107                 return NULL;
108         }
109
110         while(1) {
111                 r = read(fd, str, len);
112                 if(r < 0) {
113                         if(errno == EINTR) {
114                                 PRT_TRACE_ERR("Re-read for error(EINTR)");
115                                 continue;                       
116                         }                                               
117                         else {      
118                                 PRT_TRACE_ERR("Read fail for str");
119                                 return NULL;
120                         }                                                           
121                 } else
122                         break;
123         }
124         str[len] = 0;
125
126         return str;
127 }
128
129 static int read_message(int fd, struct sysnoti *msg)
130 {
131         int i;
132
133         msg->pid = recv_int(fd);
134         msg->cmd = recv_int(fd);
135         msg->type = recv_str(fd);
136         msg->path = recv_str(fd);
137         msg->argc = recv_int(fd);
138
139         for (i = 0; i < msg->argc; i++)
140                 msg->argv[i] = recv_str(fd);
141
142         return 0;
143 }
144
145 static inline void internal_free(char *str)
146 {
147         if (!str)
148                 free(str);
149 }
150
151 static inline void free_message(struct sysnoti *msg)
152 {
153         internal_free(msg->type);
154         internal_free(msg->path);
155         free(msg);
156 }
157
158 static int sysnoti_cb(void *data, Ecore_Fd_Handler * fd_handler)
159 {
160         int fd;
161         struct sysnoti *msg;
162         int ret = -1;
163         struct sockaddr_un client_address;
164         int client_sockfd;
165         int client_len;
166
167         if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
168                 PRT_TRACE_ERR
169                     ("ecore_main_fd_handler_active_get error , return\n");
170                 return 1;
171         }
172
173         fd = ecore_main_fd_handler_fd_get(fd_handler);
174
175         msg = malloc(sizeof(struct sysnoti));
176         if (msg == NULL) {
177                 PRT_TRACE_ERR("%s : Not enough memory", __FUNCTION__);
178                 return 1;
179         }
180
181         client_len = sizeof(client_address);
182         client_sockfd =
183             accept(fd, (struct sockaddr *)&client_address,
184                    (socklen_t *)&client_len);
185         if(client_sockfd == -1) {
186                 PRT_TRACE_ERR("socket accept error");
187                 return 1;
188         }
189
190         if (read_message(client_sockfd, msg) < 0) {
191                 PRT_TRACE_ERR("%s : recv error msg", __FUNCTION__);
192                 free(msg);
193                 write(client_sockfd, &ret, sizeof(int));
194                 close(client_sockfd);
195                 return 1;
196         }
197
198         print_sysnoti_msg(__FUNCTION__, msg);
199         if (msg->argc > SYSMAN_MAXARG) {
200                 PRT_TRACE_ERR("%s : error argument", __FUNCTION__);
201                 free_message(msg);
202                 write(client_sockfd, &ret, sizeof(int));
203                 close(client_sockfd);
204                 return 1;
205         }
206
207         switch (msg->cmd) {
208         case CALL_SYSMAN_ACTION:
209                 ret = ss_action_entry_call(msg, msg->argc, msg->argv);
210                 break;
211         default:
212                 ret = -1;
213         }
214
215         write(client_sockfd, &ret, sizeof(int));
216         close(client_sockfd);
217
218         free_message(msg);
219
220         return 1;
221 }
222
223 static int ss_sysnoti_server_init(void)
224 {
225         int fd;
226         struct sockaddr_un serveraddr;
227
228         if (access(SYSNOTI_SOCKET_PATH, F_OK) == 0)
229                 unlink(SYSNOTI_SOCKET_PATH);
230
231         fd = socket(AF_UNIX, SOCK_STREAM, 0);
232         if (fd < 0) {
233                 PRT_ERR("%s: socket create failed\n", __FUNCTION__);
234                 return -1;
235         }
236
237         if((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0 ) {
238                 PRT_ERR("%s: Socket SMACK labeling failed\n", __FUNCTION__);
239                 if(errno != EOPNOTSUPP)
240                         return -1;
241         }
242
243         if((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0 ) {
244                 PRT_ERR("%s: Socket SMACK labeling failed\n", __FUNCTION__);
245                 if(errno != EOPNOTSUPP)
246                         return -1;
247         }
248
249         bzero(&serveraddr, sizeof(struct sockaddr_un));
250         serveraddr.sun_family = AF_UNIX;
251         strncpy(serveraddr.sun_path, SYSNOTI_SOCKET_PATH,
252                 sizeof(serveraddr.sun_path));
253
254         if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) <
255             0) {
256                 PRT_ERR("%s: socket bind failed\n", __FUNCTION__);
257                 return -1;
258         }
259
260         if (chmod(SYSNOTI_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0)      /* 0777 */
261                 PRT_ERR("failed to change the socket permission");
262
263         listen(fd, 5);
264
265         PRT_INFO("socket create & listen ok\n");
266
267         return fd;
268 }
269
270 int ss_sysnoti_init(void)
271 {
272         int fd;
273         fd = ss_sysnoti_server_init();
274         ecore_main_fd_handler_add(fd, ECORE_FD_READ, sysnoti_cb, NULL, NULL,
275                                   NULL);
276         return fd;
277 }