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