blob: 4bedf9e789511572d36ec159190b9e5c01081596 [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
Dominik Behr2b9f1232016-08-02 01:11:12 -07007#include <errno.h>
David Sodman8ef20062015-01-06 09:23:40 -08008#include <fcntl.h>
9#include <limits.h>
10#include <pwd.h>
David Sodmanbbcb0522014-09-19 10:34:07 -070011#include <stdio.h>
12#include <stdlib.h>
David Sodmane46ea8a2015-03-13 15:47:12 -070013#include <string.h>
Daniel Nicoara76622c32015-03-18 17:47:54 -040014#include <sys/file.h>
David Sodmanef1ba362015-03-16 10:50:24 -070015#include <sys/stat.h>
Dominik Behr09f2b722016-10-05 12:02:04 -070016#include <sys/types.h>
17#include <sys/wait.h>
David Sodman8ef20062015-01-06 09:23:40 -080018#include <unistd.h>
David Sodmanbbcb0522014-09-19 10:34:07 -070019
David Sodmane46ea8a2015-03-13 15:47:12 -070020#include "util.h"
21
Dominik Behr09f2b722016-10-05 12:02:04 -070022static int daemon_pipe[2] = { -1, -1 };
23
Dominik Behr2b9f1232016-08-02 01:11:12 -070024static int openfd(char *path, int flags, int reqfd)
25{
26 int fd = open(path, flags);
27 if (fd < 0)
28 return -1;
29
30 if (fd == reqfd)
31 return reqfd;
32
33 if (dup2(fd, reqfd) >= 0) {
34 close(fd);
35 return reqfd;
36 }
37
38 close(fd);
39 return -1;
40}
41
42static int init_daemon_stdio(void)
43{
44 close(STDIN_FILENO);
45 close(STDOUT_FILENO);
46 close(STDERR_FILENO);
47
48 if (openfd("/dev/null", O_RDONLY, STDIN_FILENO) < 0)
49 return -1;
50
51 if (openfd("/dev/kmsg", O_WRONLY, STDOUT_FILENO) < 0)
52 return -1;
53
54 if (openfd("/dev/kmsg", O_WRONLY, STDERR_FILENO) < 0)
55 return -1;
56
57 return 0;
58}
59
Dominik Behr09f2b722016-10-05 12:02:04 -070060void daemonize(bool wait_child)
David Sodmanbbcb0522014-09-19 10:34:07 -070061{
62 pid_t pid;
David Sodmanbbcb0522014-09-19 10:34:07 -070063
Dominik Behr09f2b722016-10-05 12:02:04 -070064 if (wait_child)
65 if (pipe(daemon_pipe) < 0)
66 exit(EXIT_FAILURE);
67
David Sodmanbbcb0522014-09-19 10:34:07 -070068 pid = fork();
69 if (pid == -1)
70 return;
Dominik Behr09f2b722016-10-05 12:02:04 -070071 else if (pid != 0) {
72 if (wait_child) {
73 char code = EXIT_FAILURE;
74 close(daemon_pipe[1]);
75 if (read(daemon_pipe[0], &code, sizeof(code)) < 0) {
76 int c;
77 /* Child has died? */
78 if (errno == EPIPE)
79 if (waitpid(pid, &c, 0) >= 0)
80 exit(c); /* Propagate child exit code. */
81 /* Just report failure. */
82 exit(EXIT_FAILURE);
83 }
84 exit(code);
85 }
David Sodmanbbcb0522014-09-19 10:34:07 -070086 exit(EXIT_SUCCESS);
Dominik Behr09f2b722016-10-05 12:02:04 -070087 }
David Sodmanbbcb0522014-09-19 10:34:07 -070088
Dominik Behr09f2b722016-10-05 12:02:04 -070089 if (wait_child)
90 close(daemon_pipe[0]);
David Sodmanbbcb0522014-09-19 10:34:07 -070091 if (setsid() == -1)
92 return;
93
Dominik Behr2b9f1232016-08-02 01:11:12 -070094 init_daemon_stdio();
95}
David Sodmanbbcb0522014-09-19 10:34:07 -070096
Dominik Behr09f2b722016-10-05 12:02:04 -070097void daemon_exit_code(char code)
98{
99 if (write(daemon_pipe[1], &code, sizeof(code)) != sizeof(code)) {
100 LOG(ERROR, "failed to report exit code back to daemon parent");
101 }
102 close(daemon_pipe[1]);
103}
104
Dominik Behr2b9f1232016-08-02 01:11:12 -0700105static int is_valid_fd(int fd)
106{
107 return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
108}
David Sodmanbbcb0522014-09-19 10:34:07 -0700109
Dominik Behr2b9f1232016-08-02 01:11:12 -0700110void fix_stdio(void)
111{
112 if (!is_valid_fd(STDIN_FILENO)
113 || !is_valid_fd(STDOUT_FILENO)
114 || !is_valid_fd(STDERR_FILENO))
115 init_daemon_stdio();
David Sodmanbbcb0522014-09-19 10:34:07 -0700116}
117
118#ifdef __clang__
119__attribute__((format (__printf__, 2, 0)))
120#endif
121void LOG(int severity, const char* fmt, ...)
122{
123 va_list arg_list;
Dominik Behrb1abcba2016-04-14 14:57:21 -0700124 fprintf(stderr, "frecon(%d): ", getpid());
David Sodmanbbcb0522014-09-19 10:34:07 -0700125 va_start( arg_list, fmt);
126 vfprintf(stderr, fmt, arg_list);
127 va_end(arg_list);
128 fprintf(stderr, "\n");
129}
David Sodman8ef20062015-01-06 09:23:40 -0800130
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800131void parse_location(char* loc_str, int* x, int* y)
David Sodman8ef20062015-01-06 09:23:40 -0800132{
133 int count = 0;
134 char* savedptr;
David Sodman8ef20062015-01-06 09:23:40 -0800135 char* str;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800136 int* results[] = {x, y};
David Sodman8ef20062015-01-06 09:23:40 -0800137 long tmp;
138
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800139 for (char* token = str = loc_str; token != NULL; str = NULL) {
David Sodman8ef20062015-01-06 09:23:40 -0800140 if (count > 1)
141 break;
142
143 token = strtok_r(str, ",", &savedptr);
144 if (token) {
145 tmp = MIN(INT_MAX, strtol(token, NULL, 0));
146 *(results[count++]) = (int)tmp;
147 }
148 }
149}
150
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800151void parse_filespec(char* filespec, char* filename,
Stéphane Marchesin8fc13522015-12-14 17:02:28 -0800152 int32_t* offset_x, int32_t* offset_y, uint32_t* duration,
153 uint32_t default_duration,
154 int32_t default_x, int32_t default_y)
David Sodman8ef20062015-01-06 09:23:40 -0800155{
156 char* saved_ptr;
157 char* token;
158
159 // defaults
160 *offset_x = default_x;
161 *offset_y = default_y;
162 *duration = default_duration;
163
164 token = filespec;
165 token = strtok_r(token, ":", &saved_ptr);
166 if (token)
167 strcpy(filename, token);
168
David Sodman8ef20062015-01-06 09:23:40 -0800169 token = strtok_r(NULL, ":", &saved_ptr);
170 if (token) {
171 *duration = strtoul(token, NULL, 0);
172 token = strtok_r(NULL, ",", &saved_ptr);
173 if (token) {
174 token = strtok_r(token, ",", &saved_ptr);
175 if (token) {
176 *offset_x = strtol(token, NULL, 0);
177 token = strtok_r(token, ",", &saved_ptr);
178 if (token)
179 *offset_y = strtol(token, NULL, 0);
180 }
181 }
182 }
183}
184
185void parse_image_option(char* optionstr, char** name, char** val)
186{
187 char** result[2] = { name, val };
188 int count = 0;
David Sodman8ef20062015-01-06 09:23:40 -0800189 char* str;
190 char* savedptr;
191
Stéphane Marchesinac14d292015-12-14 15:27:18 -0800192 for (char* token = str = optionstr; token != NULL; str = NULL) {
David Sodman8ef20062015-01-06 09:23:40 -0800193 if (count > 1)
194 break;
195
196 token = strtok_r(str, ":", &savedptr);
197 if (token) {
198 *(result[count]) = malloc(strlen(token) + 1);
199 strcpy(*(result[count]), token);
200 count++;
201 }
202 }
203}
204
Dominik Behrda6df412016-08-02 12:56:42 -0700205bool write_string_to_file(const char *path, const char *s)
206{
207 int fd;
208 size_t towrite;
209 ssize_t written;
210
211 fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
212 if (!fd)
213 return false;
214
215 towrite = strlen(s);
216 written = write(fd, s, towrite);
217 close(fd);
218
219 if (written != (ssize_t)towrite) {
220 LOG(ERROR, "Failed to write string%s to %s", s, path);
221 unlink(path);
222 return false;
223 }
224 return true;
225}