2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/socket.h>
28 #define LOG_TAG "SDBD_USER_SERVICE"
31 #define SHELL_COMMAND "/bin/sh"
34 void handle_sig_term(int sig) {
35 D("sdbu signal handler called\n");
38 D("sdbu killing child with PID:%d\n",child_pid);
39 kill(child_pid,SIGKILL);
44 /* to send ptm fd to sdbd main */
45 static ssize_t send_fd(int fd, void *ptr, size_t nbytes, int sendfd)
49 struct cmsghdr *pheader;
52 char control[CMSG_SPACE(sizeof(int))];
55 memset(&msg, 0, sizeof(msg));
56 msg.msg_control = control_un.control;
57 msg.msg_controllen = sizeof(control_un.control);
59 pheader = CMSG_FIRSTHDR(&msg);
60 pheader->cmsg_len = CMSG_LEN(sizeof(int));
61 pheader->cmsg_level = SOL_SOCKET;
62 pheader->cmsg_type = SCM_RIGHTS;
63 memcpy(CMSG_DATA(pheader), &sendfd, sizeof(int));
68 iov[0].iov_base = ptr;
69 iov[0].iov_len = nbytes;
73 return sendmsg(fd, &msg, 0);
76 static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[])
79 fprintf(stderr, "sdbu argv is NULL\n");
88 execve(cmd, argv, envp);
91 int main (int argc, char **argv, char **envp)
98 ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC);
100 fprintf(stderr, "sdbu cannot open /dev/ptmx, errno: %d\n",errno);
101 E("sdbu cannot open /dev/ptmx, errno: %d\n",errno);
105 if(grantpt(ptm) || unlockpt(ptm) ||
106 ptsname_r(ptm, devname, sizeof(devname)) != 0 ){
107 fprintf(stderr, "sdbu trouble with /dev/ptmx, errno: %d\n", errno);
108 E("sdbu trouble with /dev/ptmx, errno: %d\n", errno);
112 fprintf(stderr, "sdbu ptm opening success\n");
113 D("sdbu ptm opening success\n");
115 /* Handle the SIGTERM Signal generated in case the process takes a long time to start*/
116 signal(SIGTERM, handle_sig_term);
117 D("sdbu signal handler set with, errno: %d\n", errno);
121 fprintf(stderr, "sdbu fork failed, errno: %d\n", errno);
127 /* sdbd-user's child.
128 This just open pts and exec sh */
130 D("sdbu in server process\n");
132 //sD("after sllep\n");
136 pts = unix_open(devname, O_RDWR | O_CLOEXEC);
138 fprintf(stderr, "sdbu: child failed to open pseudo-term slave %s\n", devname);
139 E("sdbu: child failed to open pseudo-term slave %s\n", devname);
142 fprintf(stderr, "sdbu: child open pts %s\n", devname);
143 E("sdbu: child open pts %s\n", devname);
147 // set OOM adjustment to zero
150 snprintf(tmptext, sizeof tmptext, "/proc/%d/oom_adj", getpid());
151 int fd = sdb_open(tmptext, O_WRONLY | O_CLOEXEC);
153 sdb_write(fd, "0", 1);
156 fprintf(stderr, "sdbu: child unable to open %s due to errno:%d\n", tmptext, errno);
157 E("sdbu: child unable to open %s due to errno:%d\n", tmptext, errno);
161 argv[0] = SHELL_COMMAND;
162 redirect_and_exec(pts, SHELL_COMMAND, argv, envp);
164 fprintf(stderr, "sdbu: child exec %s failed, errno: %d\n", SHELL_COMMAND, errno);
168 /* sdbd-user process.
169 This process open the ptm and unix socket to send ptm. */
170 /* socket create and open and bind, listen, accept and send fd here. */
172 struct sockaddr_un addr;
175 pid_t mypid = getpid();
177 D("sdbu child_pipd=%d,pid=%d,mypid=%d\n",child_pid,pid,mypid);
179 D("sdbu in child process\n");
181 //D("after sleep\n");
183 snprintf(tmptext, sizeof tmptext, "/tmp/.sdbduser_%d.sock", (int)mypid);
185 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
187 fprintf(stderr, "sdbu socket error, %d\n", errno);
188 E("sdbu socket error, %d\n", errno);
192 char *sockpath = strndup(tmptext, strlen(tmptext));
193 if (sockpath == NULL) {
194 fprintf(stderr, "sdbu socket path error, %d\n", errno);
195 E("sdbu socket path error, %d\n", errno);
199 memset(&addr, 0, sizeof(addr));
200 addr.sun_family = AF_LOCAL;
201 int len = sizeof(addr.sun_path) - 1;
202 strncpy(addr.sun_path, sockpath, len);
203 addr.sun_path[len] = '\0';
204 int slen = offsetof(struct sockaddr_un, sun_path) + strlen(sockpath);
205 if (bind(sock, (struct sockaddr *)&addr, slen) == -1) {
206 fprintf(stderr, "sdbu socket bind error, %d\n", errno);
207 E("sdbu socket bind error, %d\n", errno);
210 if (listen(sock, 5) == -1) {
211 fprintf(stderr, "sdbu listen error, %d\n", errno);
212 E("sdbu listen error, %d\n", errno);
215 D("sdbu before socket accept\n");
216 if ((s = sdb_socket_accept(sock, NULL, 0)) == -1) {
217 fprintf(stderr, "sdbu accept error, %d\n", errno);
218 E("sdbu accept error, %d\n", errno);
221 D("sdbu after socket accept\n");
222 /* send ptm fd to sdbd */
223 if (send_fd(s, &c, 1, ptm) != 0) {
224 fprintf(stderr, "sdbu send fd error, %d\n", errno);
225 E("sdbu send fd error, %d\n", errno);
231 sdb_unlink(sockpath);