This repository has been archived by the owner on Mar 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdev_twitter.c
149 lines (135 loc) · 4.13 KB
/
dev_twitter.c
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
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <linux/kmod.h>
#define DRIVER_NAME "DEV_TWITTER"
#define DRIVER_MAJOR 62
#define MAX_TWEET_LENGTH 140
#define TWEET_BUFFER_SIZE MAX_TWEET_LENGTH * 6
struct tweet_buffer {
char buffer[TWEET_BUFFER_SIZE + 1 /*For \0*/];
unsigned int pointer;
};
static int tweet(char *text) {
char *argv[] = {"/usr/local/bin/usptomo-tweet", text, NULL};
char *envp[] = {"HOME=/", "TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin", NULL};
if (call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) {
printk(KERN_WARNING "Cannot tweet text.\n");
return 1;
}
return 0;
}
static int open(struct inode *inode, struct file *file) {
struct tweet_buffer *tw_buf;
tw_buf = kmalloc(sizeof(struct tweet_buffer), GFP_KERNEL);
if (tw_buf == NULL) {
printk(KERN_WARNING "Cannot alloc memory.\n");
return -ENOMEM;
}
tw_buf->pointer = 0;
file->private_data = tw_buf;
return 0;
}
static int release(struct inode *inode, struct file *file) {
struct tweet_buffer *tw_buf;
tw_buf = file->private_data;
if (tw_buf) {
if (tw_buf->pointer > 0) {
tw_buf->buffer[tw_buf->pointer] = '\0';
tweet(tw_buf->buffer);
}
kfree(tw_buf);
file->private_data = NULL;
}
return 0;
}
static ssize_t dummy_read(struct file *file, char __user *buf, size_t count,
loff_t *f_pos) {
return 0;
}
static ssize_t write(struct file *file, const char __user *buf, size_t count,
loff_t *f_pos) {
struct tweet_buffer *tw_buf;
unsigned int read_size;
unsigned int text_pointer, text_counter;
char c_buf;
unsigned int processed_count;
tw_buf = file->private_data;
if (tw_buf) {
processed_count = 0;
while (count > processed_count) {
if (count > TWEET_BUFFER_SIZE - tw_buf->pointer) {
read_size = TWEET_BUFFER_SIZE - tw_buf->pointer;
} else {
read_size = count;
}
if (raw_copy_from_user(tw_buf->buffer + tw_buf->pointer,
buf + processed_count, read_size) != 0) {
printk(KERN_WARNING "Cannout copy data from buffer.\n");
return -EFAULT;
}
tw_buf->buffer[tw_buf->pointer + read_size] = '\0';
for (text_counter = 0, text_pointer = 0;
text_pointer < tw_buf->pointer + read_size; text_pointer++) {
if (!((unsigned char)tw_buf->buffer[text_pointer] >= 0x80 &&
0xBF >= (unsigned char)tw_buf->buffer[text_pointer])) {
text_counter++;
if (text_counter > MAX_TWEET_LENGTH) {
c_buf = tw_buf->buffer[text_pointer];
tw_buf->buffer[text_pointer] = '\0';
if (tweet(tw_buf->buffer)) {
return -EFAULT;
}
tw_buf->buffer[text_pointer] = c_buf;
break;
}
}
}
if (text_counter == MAX_TWEET_LENGTH) {
if (tweet(tw_buf->buffer)) {
return -EFAULT;
}
tw_buf->pointer = 0;
} else if (text_counter > MAX_TWEET_LENGTH) {
memcpy(tw_buf->buffer, tw_buf->buffer + text_pointer,
tw_buf->pointer + read_size - text_pointer);
tw_buf->pointer =
tw_buf->pointer + read_size - text_pointer; // is it ok?
} else {
tw_buf->pointer += read_size;
}
processed_count += read_size;
}
} else {
printk(KERN_WARNING "Cannot get tweet buffer.\n");
return -EFAULT;
}
return count;
}
struct file_operations fops = {
.open = open,
.release = release,
.read = dummy_read,
.write = write,
};
static int dev_twitter_init(void) {
printk(KERN_INFO "Starting dev_twitter\n");
register_chrdev(DRIVER_MAJOR, DRIVER_NAME, &fops);
return 0;
}
static void dev_twitter_exit(void) {
printk(KERN_INFO "Removing dev_twitter\n");
unregister_chrdev(DRIVER_MAJOR, DRIVER_NAME);
}
module_init(dev_twitter_init);
module_exit(dev_twitter_exit);
MODULE_LICENSE("MIT");