forked from runshenzhu/6.828-MIT-OS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconsole.c
128 lines (106 loc) · 2.27 KB
/
console.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
#include <inc/string.h>
#include <inc/lib.h>
void
cputchar(int ch)
{
char c = ch;
// Unlike standard Unix's putchar,
// the cputchar function _always_ outputs to the system console.
sys_cputs(&c, 1);
}
int
getchar(void)
{
unsigned char c;
int r;
// JOS does, however, support standard _input_ redirection,
// allowing the user to redirect script files to the shell and such.
// getchar() reads a character from file descriptor 0.
r = read(0, &c, 1);
if (r < 0)
return r;
if (r < 1)
return -E_EOF;
return c;
}
// "Real" console file descriptor implementation.
// The putchar/getchar functions above will still come here by default,
// but now can be redirected to files, pipes, etc., via the fd layer.
static ssize_t devcons_read(struct Fd*, void*, size_t);
static ssize_t devcons_write(struct Fd*, const void*, size_t);
static int devcons_close(struct Fd*);
static int devcons_stat(struct Fd*, struct Stat*);
struct Dev devcons =
{
.dev_id = 'c',
.dev_name = "cons",
.dev_read = devcons_read,
.dev_write = devcons_write,
.dev_close = devcons_close,
.dev_stat = devcons_stat
};
int
iscons(int fdnum)
{
int r;
struct Fd *fd;
if ((r = fd_lookup(fdnum, &fd)) < 0)
return r;
return fd->fd_dev_id == devcons.dev_id;
}
int
opencons(void)
{
int r;
struct Fd* fd;
if ((r = fd_alloc(&fd)) < 0)
return r;
if ((r = sys_page_alloc(0, fd, PTE_P|PTE_U|PTE_W|PTE_SHARE)) < 0)
return r;
fd->fd_dev_id = devcons.dev_id;
fd->fd_omode = O_RDWR;
return fd2num(fd);
}
static ssize_t
devcons_read(struct Fd *fd, void *vbuf, size_t n)
{
int c;
if (n == 0)
return 0;
while ((c = sys_cgetc()) == 0)
sys_yield();
if (c < 0)
return c;
if (c == 0x04) // ctl-d is eof
return 0;
*(char*)vbuf = c;
return 1;
}
static ssize_t
devcons_write(struct Fd *fd, const void *vbuf, size_t n)
{
int tot, m;
char buf[128];
// mistake: have to nul-terminate arg to sys_cputs,
// so we have to copy vbuf into buf in chunks and nul-terminate.
for (tot = 0; tot < n; tot += m) {
m = n - tot;
if (m > sizeof(buf) - 1)
m = sizeof(buf) - 1;
memmove(buf, (char*)vbuf + tot, m);
sys_cputs(buf, m);
}
return tot;
}
static int
devcons_close(struct Fd *fd)
{
USED(fd);
return 0;
}
static int
devcons_stat(struct Fd *fd, struct Stat *stat)
{
strcpy(stat->st_name, "<cons>");
return 0;
}