summaryrefslogtreecommitdiffstats
path: root/kernel/0001-tty-notifier.patch
blob: 6e1b29d9b5c86da0d862c7aab5f593851c965ed5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
From 5ab78e8b939366aa096c28898bbf20ddcb3a61f4 Mon Sep 17 00:00:00 2001
From: Jiri Olsa <Jiri Olsa jolsa@redhat.com>
Date: Tue, 20 Apr 2010 14:21:39 +0200
Subject: [PATCH 1/4] tty notifier

---
 drivers/char/Kconfig  |    6 ++
 drivers/char/tty_io.c |  125 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/tty.h   |   22 +++++++++
 3 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3141dd3..9be342e 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -1113,5 +1113,11 @@ config DEVPORT
 
 source "drivers/s390/char/Kconfig"
 
+config TTY_NOTIFIER
+	bool "Terminal notifier"
+	depends on EXPERIMENTAL
+	default n
+	help
+	  Interface to norify about terminals' data and state changes.
 endmenu
 
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6da962c..f0463d0 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -154,6 +154,112 @@ static void release_tty(struct tty_struct *tty, int idx);
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 
+#ifdef CONFIG_TTY_NOTIFIER
+static LIST_HEAD(tty_structs); /* linked list of tty structs */
+static ATOMIC_NOTIFIER_HEAD(tty_notifier_list);
+
+/**
+ *	register_tty_notifier - register tty notifier
+ *
+ *	Locking: none
+ */
+
+int register_tty_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&tty_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_tty_notifier);
+
+/**
+ *	unregister_tty_notifier - unregister tty notifier
+ *
+ *	Locking: none
+ */
+
+int unregister_tty_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&tty_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_tty_notifier);
+
+
+/**
+ *	notify_tty_open - notify about tty open
+ *
+ * 	Calls the tty notifier chain.
+ *
+ *	Locking: none
+ */
+
+static void notify_tty_create(struct tty_struct *tty)
+{
+	struct tty_notifier_param param = {
+		.tty = tty,
+	};
+
+	atomic_notifier_call_chain(&tty_notifier_list, TTY_NOTIFY_CREATE, &param);
+}
+
+/**
+ *	notify_tty_close - notify about tty close
+ *
+ * 	Calls the tty notifier chain.
+ *
+ *	Locking: none
+ */
+
+static void notify_tty_release(struct tty_struct *tty)
+{
+	struct tty_notifier_param param = {
+		.tty = tty,
+	};
+
+	atomic_notifier_call_chain(&tty_notifier_list, TTY_NOTIFY_RELEASE, &param);
+}
+
+/**
+ *	notify_tty_data - notify about tty data
+ *
+ * 	Calls the tty notifier chain.
+ *
+ *	Locking: none
+ */
+
+static void notify_tty_data(struct tty_struct *tty, unsigned char *buf, size_t size)
+{
+	struct tty_notifier_param param = {
+		.tty = tty,
+		.buf = buf,
+		.size = size
+	};
+
+	atomic_notifier_call_chain(&tty_notifier_list, TTY_NOTIFY_DATA, &param);
+}
+
+/**
+ *	tty_del - remove tty from the global list
+ *
+ *	Locking: tty_mutex
+ */
+
+static void tty_del(struct tty_struct *tty)
+{
+
+	mutex_lock(&tty_mutex);
+
+	/* It's the master who's on the list... */
+	if (tty->driver->type == TTY_DRIVER_TYPE_PTY)
+		if (tty->driver->subtype == PTY_TYPE_SLAVE);
+			tty = tty->link;
+
+	if (tty)
+		list_del(&tty->list);
+
+	mutex_unlock(&tty_mutex);
+}
+
+#endif
+
 /**
  *	alloc_tty_struct	-	allocate a tty object
  *
@@ -981,6 +1087,11 @@ static inline ssize_t do_tty_write(
 		ret = -EFAULT;
 		if (copy_from_user(tty->write_buf, buf, size))
 			break;
+
+#ifdef CONFIG_TTY_NOTIFIER
+		notify_tty_data(tty, tty->write_buf, size);
+#endif
+
 		ret = write(tty, file, tty->write_buf, size);
 		if (ret <= 0)
 			break;
@@ -1352,6 +1463,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
 	retval = tty_ldisc_setup(tty, tty->link);
 	if (retval)
 		goto release_mem_out;
+
+#ifdef CONFIG_TTY_NOTIFIER
+	list_add(&tty->list, &tty_structs);
+	notify_tty_create(tty);
+#endif
 	return tty;
 
 fail_no_mem:
@@ -1705,6 +1821,12 @@ int tty_release(struct inode *inode, struct file *filp)
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "freeing tty structure...");
 #endif
+
+#ifdef CONFIG_TTY_NOTIFIER
+	notify_tty_release(tty);
+	tty_del(tty);
+#endif
+
 	/*
 	 * Ask the line discipline code to release its structures
 	 */
@@ -2770,6 +2892,9 @@ void initialize_tty_struct(struct tty_struct *tty,
 	spin_lock_init(&tty->read_lock);
 	spin_lock_init(&tty->ctrl_lock);
 	INIT_LIST_HEAD(&tty->tty_files);
+#ifdef CONFIG_TTY_NOTIFIER
+	INIT_LIST_HEAD(&tty->list);
+#endif
 	INIT_WORK(&tty->SAK_work, do_SAK_work);
 
 	tty->driver = driver;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4409967..7d57719 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -13,6 +13,7 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_ldisc.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
 
 #include <asm/system.h>
 
@@ -324,8 +325,29 @@ struct tty_struct {
 	/* If the tty has a pending do_SAK, queue it here - akpm */
 	struct work_struct SAK_work;
 	struct tty_port *port;
+#ifdef CONFIG_TTY_NOTIFIER
+	struct list_head list;
+#endif
+};
+
+
+#ifdef CONFIG_TTY_NOTIFIER
+
+#define TTY_NOTIFY_DATA		1
+#define TTY_NOTIFY_CREATE	2
+#define TTY_NOTIFY_RELEASE	3
+
+struct tty_notifier_param {
+	struct tty_struct *tty;
+	unsigned char *buf;
+	size_t size;
 };
 
+extern int register_tty_notifier(struct notifier_block *nb);
+extern int unregister_tty_notifier(struct notifier_block *nb);
+
+#endif /* CONFIG_TTY_NOTIFIER */
+
 /* tty magic number */
 #define TTY_MAGIC		0x5401
 
-- 
1.6.6.1