1 /*
2
3 Copyright (c) 2003-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37 #include <stdio.h>
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44 #ifdef HAVE_SYS_UN_H
45 #include <sys/un.h>
46 #endif
47 #ifdef HAVE_PWD_H
48 #include <pwd.h>
49 #endif
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53 #ifdef HAVE_STRING_H
54 #include <string.h>
55 #endif
56 #ifdef HAVE_STDLIB_H
57 #include <stdlib.h>
58 #endif
59 #ifdef HAVE_SYS_STAT_H
60 #include <sys/stat.h>
61 #endif
62
63 #include <uim/uim.h>
64 #include <uim/uim-helper.h>
65 #include "uim-posix.h"
66 #include "udsock.h"
67
68 static int s_send_sockfd = -1;
69 static int s_recv_sockfd = -1;
70 static struct sockaddr_un s_servaddr;
71
72 uim_bool
get_ud_path(char * path,int len)73 get_ud_path(char *path, int len)
74 {
75 if (len <= 0)
76 return UIM_FALSE;
77
78 if (!uim_get_config_path(path, len, !uim_helper_is_setugid())) {
79 path[0] = '\0';
80 return UIM_FALSE;
81 }
82
83 if (strlcat(path, "/fep", len) >= (size_t)len) {
84 path[0] = '\0';
85 return UIM_FALSE;
86 }
87
88 if (!uim_check_dir(path)) {
89 path[0] = '\0';
90 return UIM_FALSE;
91 }
92
93 return UIM_TRUE;
94 }
95
96
usersockname(const char * file)97 const char *usersockname(const char *file)
98 {
99 static char buf[UNIX_PATH_MAX];
100 char filebuf[UNIX_PATH_MAX];
101 char sock_dir[UNIX_PATH_MAX];
102
103 if (file != NULL && file[0] == '/') {
104 return file;
105 }
106
107 if (file == NULL) {
108 strlcpy(filebuf, "backtick", UNIX_PATH_MAX);
109 } else {
110 strlcpy(filebuf, file, UNIX_PATH_MAX);
111 }
112
113 if (!get_ud_path(sock_dir, sizeof(sock_dir))) {
114 sendline("uim-fep cannot create directory");
115 /* exit(EXIT_FAILURE); */
116 }
117 snprintf(buf, sizeof(buf), "%s/%s", sock_dir, filebuf);
118
119 return buf;
120 }
121
init_sendsocket(const char * sock_path)122 void init_sendsocket(const char *sock_path)
123 {
124 const char *path;
125
126 path = usersockname(sock_path);
127 s_send_sockfd = socket(PF_UNIX, SOCK_DGRAM, 0);
128 memset(&s_servaddr, 0, sizeof(s_servaddr));
129 s_servaddr.sun_family = AF_UNIX;
130 strlcpy(s_servaddr.sun_path, path, UNIX_PATH_MAX);
131 }
132
sendline(const char * buf)133 void sendline(const char *buf)
134 {
135 sendto(s_send_sockfd, buf, strlen(buf), 0, (struct sockaddr *)&s_servaddr, sizeof(s_servaddr));
136 }
137
138 /*
139 * socketのファイルディスクリプタを返す。
140 * エラーの場合は-1を返し、errnoを設定する。
141 */
init_recvsocket(const char * sock_path)142 void init_recvsocket(const char *sock_path)
143 {
144 const char *path;
145
146 path = usersockname(sock_path);
147 unlink(path);
148 s_recv_sockfd = socket(PF_UNIX, SOCK_DGRAM, 0);
149 memset(&s_servaddr, 0, sizeof(s_servaddr));
150 s_servaddr.sun_family = AF_UNIX;
151 strlcpy(s_servaddr.sun_path, path, UNIX_PATH_MAX);
152 if (bind(s_recv_sockfd, (struct sockaddr *)&s_servaddr, sizeof(s_servaddr)) < 0) {
153 perror(path);
154 exit(EXIT_FAILURE);
155 }
156 chmod(path, S_IRUSR|S_IWUSR);
157 }
158
close_socket(void)159 void close_socket(void)
160 {
161 if (s_send_sockfd != -1) {
162 close(s_send_sockfd);
163 }
164 if (s_recv_sockfd != -1) {
165 close(s_recv_sockfd);
166 }
167 }
168
recvline(char * buf,int n)169 int recvline(char *buf, int n)
170 {
171 return recvfrom(s_recv_sockfd, buf, n, 0, NULL, NULL);
172 }
173