4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/types.h>
22 #include <sys/socket.h>
31 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
32 #define RETRY_READ_COUNT 5
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);
43 static void print_sysnoti_msg(const char *title, struct sysnoti *msg)
46 char exe_name[PATH_MAX];
48 if (get_cmdline_name(msg->pid, exe_name, PATH_MAX) < 0)
49 snprintf(exe_name, sizeof(exe_name), "Unknown (maybe dead)");
51 _SD("pid : %d name: %s cmd : %d type : %s path : %s",
52 msg->pid, exe_name, msg->cmd, msg->type, msg->path);
55 static inline int recv_int(int fd)
59 while (retry_count < RETRY_READ_COUNT) {
60 r = read(fd, &val, sizeof(int));
63 _D("Re-read for error(EINTR)");
68 _E("Read fail for int");
78 static inline char *recv_str(int fd)
84 while (retry_count < RETRY_READ_COUNT) {
85 r = read(fd, &len, sizeof(int));
88 _D("Re-read for error(EINTR)");
93 _E("Read fail for str length");
99 if (retry_count == RETRY_READ_COUNT) {
100 _E("Read retry failed");
106 if (len >= INT_MAX) {
107 _E("size is over INT_MAX");
111 str = (char *)malloc(len + 1);
113 _E("Not enough memory");
117 while (retry_count < RETRY_READ_COUNT) {
118 r = read(fd, str, len);
121 _D("Re-read for error(EINTR)");
125 _E("Read fail for str");
133 if (retry_count == RETRY_READ_COUNT) {
134 _E("Read retry failed");
144 static int read_message(int fd, struct sysnoti *msg)
148 if ((msg->pid = recv_int(fd)) == -1)
150 if ((msg->cmd = recv_int(fd)) == -1)
152 if ((msg->type = recv_str(fd)) == NULL)
154 msg->path = recv_str(fd);
155 msg->argc = recv_int(fd);
159 for (i = 0; i < msg->argc; i++)
160 msg->argv[i] = recv_str(fd);
165 static inline void internal_free(char *str)
171 static inline void free_message(struct sysnoti *msg)
173 internal_free(msg->type);
174 internal_free(msg->path);
178 static Eina_Bool sysnoti_cb(void *data, Ecore_Fd_Handler * fd_handler)
182 struct sockaddr_un client_address;
186 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
187 _E("ecore_main_fd_handler_active_get error , return");
191 msg = malloc(sizeof(struct sysnoti));
193 _E("Not enough memory");
197 client_len = sizeof(client_address);
198 client_sockfd = accept(sysnoti_fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
200 if (client_sockfd == -1) {
201 _E("socket accept error");
205 if (read_message(client_sockfd, msg) < 0) {
206 _E("recv error msg");
207 print_sysnoti_msg(__FUNCTION__, msg);
209 write(client_sockfd, &ret, sizeof(int));
210 close(client_sockfd);
211 __sysnoti_stop(sysnoti_fd);
216 print_sysnoti_msg(__FUNCTION__, msg);
217 if (msg->argc > SYSMAN_MAXARG) {
218 _E("error argument");
220 write(client_sockfd, &ret, sizeof(int));
221 close(client_sockfd);
228 ret = register_msg(msg);
233 ret = notify_msg(msg, client_sockfd);
240 write(client_sockfd, &ret, sizeof(int));
241 close(client_sockfd);
248 static int sysnoti_server_init(void)
251 struct sockaddr_un serveraddr;
253 if (access(SYSNOTI_SOCKET_PATH, F_OK) == 0)
254 unlink(SYSNOTI_SOCKET_PATH);
256 fd = socket(AF_UNIX, SOCK_STREAM, 0);
258 _E("socket create failed");
261 if((fsetxattr(fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0 ) {
262 _E("Socket SMACK labeling failed");
263 if(errno != EOPNOTSUPP) {
269 if((fsetxattr(fd, "security.SMACK64IPIN", "*", 2, 0)) < 0 ) {
270 _E("Socket SMACK labeling failed");
271 if(errno != EOPNOTSUPP) {
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));
282 if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) < 0) {
283 _E("socket bind failed");
288 if (chmod(SYSNOTI_SOCKET_PATH, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) /* 0777 */
289 _E("failed to change the socket permission");
291 if (listen(fd, 5) < 0) {
292 _E("failed to listen");
300 static int __sysnoti_start(void)
302 sysnoti_fd = sysnoti_server_init();
303 if ( sysnoti_fd < 0 )
305 sysnoti_efd = ecore_main_fd_handler_add(sysnoti_fd, ECORE_FD_READ, sysnoti_cb, NULL, NULL,
308 _E("error ecore_main_fd_handler_add");
315 static int __sysnoti_stop(int fd)
318 ecore_main_fd_handler_del(sysnoti_efd);
328 static void sysnoti_init(void *data)
330 struct main_data *ad = (struct main_data*)data;
332 if (__sysnoti_start() == -1)
333 _E("fail sys socket fd init");
336 static const struct device_ops sysnoti_device_ops = {
337 .priority = DEVICE_PRIORITY_NORMAL,
339 .init = sysnoti_init,
342 DEVICE_OPS_REGISTER(&sysnoti_device_ops)