1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <unistd.h>
8#include <errno.h>
9#include "user.h"
10#include "mconsole.h"
11#include "os.h"
12#include "choose-mode.h"
13#include "mode.h"
14
15struct dog_data {
16	int stdin;
17	int stdout;
18	int close_me[2];
19};
20
21static void pre_exec(void *d)
22{
23	struct dog_data *data = d;
24
25	dup2(data->stdin, 0);
26	dup2(data->stdout, 1);
27	dup2(data->stdout, 2);
28	os_close_file(data->stdin);
29	os_close_file(data->stdout);
30	os_close_file(data->close_me[0]);
31	os_close_file(data->close_me[1]);
32}
33
34int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
35{
36	struct dog_data data;
37	int in_fds[2], out_fds[2], pid, n, err;
38	char pid_buf[sizeof("nnnnn\0")], c;
39	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
40	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
41				  NULL };
42	char **args = NULL;
43
44	err = os_pipe(in_fds, 1, 0);
45	if(err < 0){
46		printk("harddog_open - os_pipe failed, err = %d\n", -err);
47		goto out;
48	}
49
50	err = os_pipe(out_fds, 1, 0);
51	if(err < 0){
52		printk("harddog_open - os_pipe failed, err = %d\n", -err);
53		goto out_close_in;
54	}
55
56	data.stdin = out_fds[0];
57	data.stdout = in_fds[1];
58	data.close_me[0] = out_fds[1];
59	data.close_me[1] = in_fds[0];
60
61	if(sock != NULL){
62		mconsole_args[2] = sock;
63		args = mconsole_args;
64	}
65	else {
66		sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid()));
67		args = pid_args;
68	}
69
70	pid = run_helper(pre_exec, &data, args, NULL);
71
72	os_close_file(out_fds[0]);
73	os_close_file(in_fds[1]);
74
75	if(pid < 0){
76		err = -pid;
77		printk("harddog_open - run_helper failed, errno = %d\n", -err);
78		goto out_close_out;
79	}
80
81	n = os_read_file(in_fds[0], &c, sizeof(c));
82	if(n == 0){
83		printk("harddog_open - EOF on watchdog pipe\n");
84		helper_wait(pid);
85		err = -EIO;
86		goto out_close_out;
87	}
88	else if(n < 0){
89		printk("harddog_open - read of watchdog pipe failed, "
90		       "err = %d\n", -n);
91		helper_wait(pid);
92		err = n;
93		goto out_close_out;
94	}
95	*in_fd_ret = in_fds[0];
96	*out_fd_ret = out_fds[1];
97	return 0;
98
99 out_close_in:
100	os_close_file(in_fds[0]);
101	os_close_file(in_fds[1]);
102 out_close_out:
103	os_close_file(out_fds[0]);
104	os_close_file(out_fds[1]);
105 out:
106	return err;
107}
108
109void stop_watchdog(int in_fd, int out_fd)
110{
111	os_close_file(in_fd);
112	os_close_file(out_fd);
113}
114
115int ping_watchdog(int fd)
116{
117	int n;
118	char c = '\n';
119
120	n = os_write_file(fd, &c, sizeof(c));
121	if(n != sizeof(c)){
122		printk("ping_watchdog - write failed, err = %d\n", -n);
123		if(n < 0)
124			return n;
125		return -EIO;
126	}
127	return 1;
128
129}
130