162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <stdio.h> 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <errno.h> 962306a36Sopenharmony_ci#include <os.h> 1062306a36Sopenharmony_ci#include "harddog.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct dog_data { 1362306a36Sopenharmony_ci int stdin_fd; 1462306a36Sopenharmony_ci int stdout_fd; 1562306a36Sopenharmony_ci int close_me[2]; 1662306a36Sopenharmony_ci}; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void pre_exec(void *d) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci struct dog_data *data = d; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci dup2(data->stdin_fd, 0); 2362306a36Sopenharmony_ci dup2(data->stdout_fd, 1); 2462306a36Sopenharmony_ci dup2(data->stdout_fd, 2); 2562306a36Sopenharmony_ci close(data->stdin_fd); 2662306a36Sopenharmony_ci close(data->stdout_fd); 2762306a36Sopenharmony_ci close(data->close_me[0]); 2862306a36Sopenharmony_ci close(data->close_me[1]); 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciint start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci struct dog_data data; 3462306a36Sopenharmony_ci int in_fds[2], out_fds[2], pid, n, err; 3562306a36Sopenharmony_ci char pid_buf[sizeof("nnnnnnn\0")], c; 3662306a36Sopenharmony_ci char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; 3762306a36Sopenharmony_ci char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, 3862306a36Sopenharmony_ci NULL }; 3962306a36Sopenharmony_ci char **args = NULL; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci err = os_pipe(in_fds, 1, 0); 4262306a36Sopenharmony_ci if (err < 0) { 4362306a36Sopenharmony_ci printk("harddog_open - os_pipe failed, err = %d\n", -err); 4462306a36Sopenharmony_ci goto out; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci err = os_pipe(out_fds, 1, 0); 4862306a36Sopenharmony_ci if (err < 0) { 4962306a36Sopenharmony_ci printk("harddog_open - os_pipe failed, err = %d\n", -err); 5062306a36Sopenharmony_ci goto out_close_in; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci data.stdin_fd = out_fds[0]; 5462306a36Sopenharmony_ci data.stdout_fd = in_fds[1]; 5562306a36Sopenharmony_ci data.close_me[0] = out_fds[1]; 5662306a36Sopenharmony_ci data.close_me[1] = in_fds[0]; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (sock != NULL) { 5962306a36Sopenharmony_ci mconsole_args[2] = sock; 6062306a36Sopenharmony_ci args = mconsole_args; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci else { 6362306a36Sopenharmony_ci /* XXX The os_getpid() is not SMP correct */ 6462306a36Sopenharmony_ci sprintf(pid_buf, "%d", os_getpid()); 6562306a36Sopenharmony_ci args = pid_args; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci pid = run_helper(pre_exec, &data, args); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci close(out_fds[0]); 7162306a36Sopenharmony_ci close(in_fds[1]); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (pid < 0) { 7462306a36Sopenharmony_ci err = -pid; 7562306a36Sopenharmony_ci printk("harddog_open - run_helper failed, errno = %d\n", -err); 7662306a36Sopenharmony_ci goto out_close_out; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci n = read(in_fds[0], &c, sizeof(c)); 8062306a36Sopenharmony_ci if (n == 0) { 8162306a36Sopenharmony_ci printk("harddog_open - EOF on watchdog pipe\n"); 8262306a36Sopenharmony_ci helper_wait(pid); 8362306a36Sopenharmony_ci err = -EIO; 8462306a36Sopenharmony_ci goto out_close_out; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci else if (n < 0) { 8762306a36Sopenharmony_ci printk("harddog_open - read of watchdog pipe failed, " 8862306a36Sopenharmony_ci "err = %d\n", errno); 8962306a36Sopenharmony_ci helper_wait(pid); 9062306a36Sopenharmony_ci err = n; 9162306a36Sopenharmony_ci goto out_close_out; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci *in_fd_ret = in_fds[0]; 9462306a36Sopenharmony_ci *out_fd_ret = out_fds[1]; 9562306a36Sopenharmony_ci return 0; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci out_close_in: 9862306a36Sopenharmony_ci close(in_fds[0]); 9962306a36Sopenharmony_ci close(in_fds[1]); 10062306a36Sopenharmony_ci out_close_out: 10162306a36Sopenharmony_ci close(out_fds[0]); 10262306a36Sopenharmony_ci close(out_fds[1]); 10362306a36Sopenharmony_ci out: 10462306a36Sopenharmony_ci return err; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_civoid stop_watchdog(int in_fd, int out_fd) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci close(in_fd); 11062306a36Sopenharmony_ci close(out_fd); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciint ping_watchdog(int fd) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci int n; 11662306a36Sopenharmony_ci char c = '\n'; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci n = write(fd, &c, sizeof(c)); 11962306a36Sopenharmony_ci if (n != sizeof(c)) { 12062306a36Sopenharmony_ci printk("ping_watchdog - write failed, ret = %d, err = %d\n", 12162306a36Sopenharmony_ci n, errno); 12262306a36Sopenharmony_ci if (n < 0) 12362306a36Sopenharmony_ci return n; 12462306a36Sopenharmony_ci return -EIO; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci return 1; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci} 129