2018-09-25 09:22:51 -07:00
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
2018-10-24 17:44:45 -07:00
|
|
|
unsigned char c;
|
2018-09-25 09:22:51 -07:00
|
|
|
int r;
|
2018-10-24 17:44:45 -07:00
|
|
|
|
|
|
|
// 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)
|
2018-10-06 06:52:47 -07:00
|
|
|
sys_yield();
|
2018-10-24 17:44:45 -07:00
|
|
|
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;
|
2018-09-25 09:22:51 -07:00
|
|
|
}
|
|
|
|
|
2018-10-24 17:44:45 -07:00
|
|
|
static int
|
|
|
|
devcons_stat(struct Fd *fd, struct Stat *stat)
|
|
|
|
{
|
|
|
|
strcpy(stat->st_name, "<cons>");
|
|
|
|
return 0;
|
|
|
|
}
|
2018-09-25 09:22:51 -07:00
|
|
|
|