pagetable lab initialized
This commit is contained in:
21
user/cat.c
21
user/cat.c
@@ -1,35 +1,38 @@
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "user/user.h"
|
||||
|
||||
char buf[512];
|
||||
|
||||
void cat(int fd) {
|
||||
void
|
||||
cat(int fd)
|
||||
{
|
||||
int n;
|
||||
|
||||
while ((n = read(fd, buf, sizeof(buf))) > 0) {
|
||||
while((n = read(fd, buf, sizeof(buf))) > 0) {
|
||||
if (write(1, buf, n) != n) {
|
||||
fprintf(2, "cat: write error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (n < 0) {
|
||||
if(n < 0){
|
||||
fprintf(2, "cat: read error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (argc <= 1) {
|
||||
if(argc <= 1){
|
||||
cat(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if ((fd = open(argv[i], O_RDONLY)) < 0) {
|
||||
for(i = 1; i < argc; i++){
|
||||
if((fd = open(argv[i], O_RDONLY)) < 0){
|
||||
fprintf(2, "cat: cannot open %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ init:
|
||||
# char *argv[] = { init, 0 };
|
||||
.p2align 2
|
||||
argv:
|
||||
.long init
|
||||
.long 0
|
||||
.quad init
|
||||
.quad 0
|
||||
|
||||
50
user/ls.c
50
user/ls.c
@@ -1,81 +1,87 @@
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/fs.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "user/user.h"
|
||||
#include "kernel/fs.h"
|
||||
#include "kernel/fcntl.h"
|
||||
|
||||
char *fmtname(char *path) {
|
||||
static char buf[DIRSIZ + 1];
|
||||
char*
|
||||
fmtname(char *path)
|
||||
{
|
||||
static char buf[DIRSIZ+1];
|
||||
char *p;
|
||||
|
||||
// Find first character after last slash.
|
||||
for (p = path + strlen(path); p >= path && *p != '/'; p--)
|
||||
for(p=path+strlen(path); p >= path && *p != '/'; p--)
|
||||
;
|
||||
p++;
|
||||
|
||||
// Return blank-padded name.
|
||||
if (strlen(p) >= DIRSIZ)
|
||||
if(strlen(p) >= DIRSIZ)
|
||||
return p;
|
||||
memmove(buf, p, strlen(p));
|
||||
memset(buf + strlen(p), ' ', DIRSIZ - strlen(p));
|
||||
memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ls(char *path) {
|
||||
void
|
||||
ls(char *path)
|
||||
{
|
||||
char buf[512], *p;
|
||||
int fd;
|
||||
struct dirent de;
|
||||
struct stat st;
|
||||
|
||||
if ((fd = open(path, O_RDONLY)) < 0) {
|
||||
if((fd = open(path, O_RDONLY)) < 0){
|
||||
fprintf(2, "ls: cannot open %s\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
if(fstat(fd, &st) < 0){
|
||||
fprintf(2, "ls: cannot stat %s\n", path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (st.type) {
|
||||
switch(st.type){
|
||||
case T_DEVICE:
|
||||
case T_FILE:
|
||||
printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size);
|
||||
printf("%s %d %d %d\n", fmtname(path), st.type, st.ino, (int) st.size);
|
||||
break;
|
||||
|
||||
case T_DIR:
|
||||
if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) {
|
||||
if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
|
||||
printf("ls: path too long\n");
|
||||
break;
|
||||
}
|
||||
strcpy(buf, path);
|
||||
p = buf + strlen(buf);
|
||||
p = buf+strlen(buf);
|
||||
*p++ = '/';
|
||||
while (read(fd, &de, sizeof(de)) == sizeof(de)) {
|
||||
if (de.inum == 0)
|
||||
while(read(fd, &de, sizeof(de)) == sizeof(de)){
|
||||
if(de.inum == 0)
|
||||
continue;
|
||||
memmove(p, de.name, DIRSIZ);
|
||||
p[DIRSIZ] = 0;
|
||||
if (stat(buf, &st) < 0) {
|
||||
if(stat(buf, &st) < 0){
|
||||
printf("ls: cannot stat %s\n", buf);
|
||||
continue;
|
||||
}
|
||||
printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
|
||||
printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, (int) st.size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
if(argc < 2){
|
||||
ls(".");
|
||||
exit(0);
|
||||
}
|
||||
for (i = 1; i < argc; i++)
|
||||
for(i=1; i<argc; i++)
|
||||
ls(argv[i]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
164
user/pgtbltest.c
Normal file
164
user/pgtbltest.c
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "kernel/param.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/riscv.h"
|
||||
#include "user/user.h"
|
||||
|
||||
#define N (8 * (1 << 20))
|
||||
|
||||
void print_pgtbl();
|
||||
void print_kpgtbl();
|
||||
void ugetpid_test();
|
||||
void pgaccess_test();
|
||||
void superpg_test();
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
print_pgtbl();
|
||||
ugetpid_test();
|
||||
print_kpgtbl();
|
||||
pgaccess_test();
|
||||
superpg_test();
|
||||
printf("pgtbltest: all tests succeeded\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *testname = "???";
|
||||
|
||||
void
|
||||
err(char *why)
|
||||
{
|
||||
printf("pgtbltest: %s failed: %s, pid=%d\n", testname, why, getpid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
print_pte(uint64 va)
|
||||
{
|
||||
pte_t pte = (pte_t) pgpte((void *) va);
|
||||
printf("va 0x%lx pte 0x%lx pa 0x%lx perm 0x%lx\n", va, pte, PTE2PA(pte), PTE_FLAGS(pte));
|
||||
}
|
||||
|
||||
void
|
||||
print_pgtbl()
|
||||
{
|
||||
printf("print_pgtbl starting\n");
|
||||
for (uint64 i = 0; i < 10; i++) {
|
||||
print_pte(i * PGSIZE);
|
||||
}
|
||||
uint64 top = MAXVA/PGSIZE;
|
||||
for (uint64 i = top-10; i < top; i++) {
|
||||
print_pte(i * PGSIZE);
|
||||
}
|
||||
printf("print_pgtbl: OK\n");
|
||||
}
|
||||
|
||||
void
|
||||
ugetpid_test()
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("ugetpid_test starting\n");
|
||||
testname = "ugetpid_test";
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
int ret = fork();
|
||||
if (ret != 0) {
|
||||
wait(&ret);
|
||||
if (ret != 0)
|
||||
exit(1);
|
||||
continue;
|
||||
}
|
||||
if (getpid() != ugetpid())
|
||||
err("missmatched PID");
|
||||
exit(0);
|
||||
}
|
||||
printf("ugetpid_test: OK\n");
|
||||
}
|
||||
|
||||
void
|
||||
print_kpgtbl()
|
||||
{
|
||||
printf("print_kpgtbl starting\n");
|
||||
kpgtbl();
|
||||
printf("print_kpgtbl: OK\n");
|
||||
}
|
||||
|
||||
void
|
||||
pgaccess_test()
|
||||
{
|
||||
char *buf;
|
||||
unsigned int abits;
|
||||
printf("pgaccess_test starting\n");
|
||||
testname = "pgaccess_test";
|
||||
buf = malloc(32 * PGSIZE);
|
||||
if (pgaccess(buf, 32, &abits) < 0)
|
||||
err("pgaccess failed");
|
||||
buf[PGSIZE * 1] += 1;
|
||||
buf[PGSIZE * 2] += 1;
|
||||
buf[PGSIZE * 30] += 1;
|
||||
if (pgaccess(buf, 32, &abits) < 0)
|
||||
err("pgaccess failed");
|
||||
if (abits != ((1 << 1) | (1 << 2) | (1 << 30)))
|
||||
err("incorrect access bits set");
|
||||
free(buf);
|
||||
printf("pgaccess_test: OK\n");
|
||||
}
|
||||
|
||||
void
|
||||
supercheck(uint64 s)
|
||||
{
|
||||
pte_t last_pte = 0;
|
||||
|
||||
for (uint64 p = s; p < s + 512 * PGSIZE; p += PGSIZE) {
|
||||
pte_t pte = (pte_t) pgpte((void *) p);
|
||||
if(pte == 0)
|
||||
err("no pte");
|
||||
if ((uint64) last_pte != 0 && pte != last_pte) {
|
||||
err("pte different");
|
||||
}
|
||||
if((pte & PTE_V) == 0 || (pte & PTE_R) == 0 || (pte & PTE_W) == 0){
|
||||
err("pte wrong");
|
||||
}
|
||||
last_pte = pte;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 512; i += PGSIZE){
|
||||
*(int*)(s+i) = i;
|
||||
}
|
||||
|
||||
for(int i = 0; i < 512; i += PGSIZE){
|
||||
if(*(int*)(s+i) != i)
|
||||
err("wrong value");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
superpg_test()
|
||||
{
|
||||
int pid;
|
||||
|
||||
printf("superpg_test starting\n");
|
||||
testname = "superpg_test";
|
||||
|
||||
char *end = sbrk(N);
|
||||
if (end == 0 || end == (char*)0xffffffffffffffff)
|
||||
err("sbrk failed");
|
||||
|
||||
uint64 s = SUPERPGROUNDUP((uint64) end);
|
||||
supercheck(s);
|
||||
if((pid = fork()) < 0) {
|
||||
err("fork");
|
||||
} else if(pid == 0) {
|
||||
supercheck(s);
|
||||
exit(0);
|
||||
} else {
|
||||
int status;
|
||||
wait(&status);
|
||||
if (status != 0) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
printf("superpg_test: OK\n");
|
||||
}
|
||||
115
user/printf.c
115
user/printf.c
@@ -1,20 +1,26 @@
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "user/user.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static char digits[] = "0123456789ABCDEF";
|
||||
|
||||
static void putc(int fd, char c) { write(fd, &c, 1); }
|
||||
static void
|
||||
putc(int fd, char c)
|
||||
{
|
||||
write(fd, &c, 1);
|
||||
}
|
||||
|
||||
static void printint(int fd, int xx, int base, int sgn) {
|
||||
static void
|
||||
printint(int fd, int xx, int base, int sgn)
|
||||
{
|
||||
char buf[16];
|
||||
int i, neg;
|
||||
uint x;
|
||||
|
||||
neg = 0;
|
||||
if (sgn && xx < 0) {
|
||||
if(sgn && xx < 0){
|
||||
neg = 1;
|
||||
x = -xx;
|
||||
} else {
|
||||
@@ -22,17 +28,18 @@ static void printint(int fd, int xx, int base, int sgn) {
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
do{
|
||||
buf[i++] = digits[x % base];
|
||||
} while ((x /= base) != 0);
|
||||
if (neg)
|
||||
}while((x /= base) != 0);
|
||||
if(neg)
|
||||
buf[i++] = '-';
|
||||
|
||||
while (--i >= 0)
|
||||
while(--i >= 0)
|
||||
putc(fd, buf[i]);
|
||||
}
|
||||
|
||||
static void printptr(int fd, uint64 x) {
|
||||
static void
|
||||
printptr(int fd, uint64 x) {
|
||||
int i;
|
||||
putc(fd, '0');
|
||||
putc(fd, 'x');
|
||||
@@ -41,58 +48,108 @@ static void printptr(int fd, uint64 x) {
|
||||
}
|
||||
|
||||
// Print to the given fd. Only understands %d, %x, %p, %s.
|
||||
void vprintf(int fd, const char *fmt, va_list ap) {
|
||||
void
|
||||
vprintf(int fd, const char *fmt, va_list ap)
|
||||
{
|
||||
char *s;
|
||||
int c, i, state;
|
||||
int c0, c1, c2, i, state;
|
||||
|
||||
state = 0;
|
||||
for (i = 0; fmt[i]; i++) {
|
||||
c = fmt[i] & 0xff;
|
||||
if (state == 0) {
|
||||
if (c == '%') {
|
||||
for(i = 0; fmt[i]; i++){
|
||||
c0 = fmt[i] & 0xff;
|
||||
if(state == 0){
|
||||
if(c0 == '%'){
|
||||
state = '%';
|
||||
} else {
|
||||
putc(fd, c);
|
||||
putc(fd, c0);
|
||||
}
|
||||
} else if (state == '%') {
|
||||
if (c == 'd') {
|
||||
} else if(state == '%'){
|
||||
c1 = c2 = 0;
|
||||
if(c0) c1 = fmt[i+1] & 0xff;
|
||||
if(c1) c2 = fmt[i+2] & 0xff;
|
||||
if(c0 == 'd'){
|
||||
printint(fd, va_arg(ap, int), 10, 1);
|
||||
} else if (c == 'l') {
|
||||
} else if(c0 == 'l' && c1 == 'd'){
|
||||
printint(fd, va_arg(ap, uint64), 10, 1);
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'd'){
|
||||
printint(fd, va_arg(ap, uint64), 10, 1);
|
||||
i += 2;
|
||||
} else if(c0 == 'u'){
|
||||
printint(fd, va_arg(ap, int), 10, 0);
|
||||
} else if(c0 == 'l' && c1 == 'u'){
|
||||
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||
} else if (c == 'x') {
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'u'){
|
||||
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||
i += 2;
|
||||
} else if(c0 == 'x'){
|
||||
printint(fd, va_arg(ap, int), 16, 0);
|
||||
} else if (c == 'p') {
|
||||
} else if(c0 == 'l' && c1 == 'x'){
|
||||
printint(fd, va_arg(ap, uint64), 16, 0);
|
||||
i += 1;
|
||||
} else if(c0 == 'l' && c1 == 'l' && c2 == 'x'){
|
||||
printint(fd, va_arg(ap, uint64), 16, 0);
|
||||
i += 2;
|
||||
} else if(c0 == 'p'){
|
||||
printptr(fd, va_arg(ap, uint64));
|
||||
} else if (c == 's') {
|
||||
s = va_arg(ap, char *);
|
||||
if (s == 0)
|
||||
} else if(c0 == 's'){
|
||||
if((s = va_arg(ap, char*)) == 0)
|
||||
s = "(null)";
|
||||
while (*s != 0) {
|
||||
for(; *s; s++)
|
||||
putc(fd, *s);
|
||||
} else if(c0 == '%'){
|
||||
putc(fd, '%');
|
||||
} else {
|
||||
// Unknown % sequence. Print it to draw attention.
|
||||
putc(fd, '%');
|
||||
putc(fd, c0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if(c == 'd'){
|
||||
printint(fd, va_arg(ap, int), 10, 1);
|
||||
} else if(c == 'l') {
|
||||
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||
} else if(c == 'x') {
|
||||
printint(fd, va_arg(ap, int), 16, 0);
|
||||
} else if(c == 'p') {
|
||||
printptr(fd, va_arg(ap, uint64));
|
||||
} else if(c == 's'){
|
||||
s = va_arg(ap, char*);
|
||||
if(s == 0)
|
||||
s = "(null)";
|
||||
while(*s != 0){
|
||||
putc(fd, *s);
|
||||
s++;
|
||||
}
|
||||
} else if (c == 'c') {
|
||||
} else if(c == 'c'){
|
||||
putc(fd, va_arg(ap, uint));
|
||||
} else if (c == '%') {
|
||||
} else if(c == '%'){
|
||||
putc(fd, c);
|
||||
} else {
|
||||
// Unknown % sequence. Print it to draw attention.
|
||||
putc(fd, '%');
|
||||
putc(fd, c);
|
||||
}
|
||||
#endif
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fprintf(int fd, const char *fmt, ...) {
|
||||
void
|
||||
fprintf(int fd, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fd, fmt, ap);
|
||||
}
|
||||
|
||||
void printf(const char *fmt, ...) {
|
||||
void
|
||||
printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
243
user/sh.c
243
user/sh.c
@@ -1,16 +1,15 @@
|
||||
// Shell.
|
||||
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/fs.h"
|
||||
#include "kernel/types.h"
|
||||
#include "user/user.h"
|
||||
#include "kernel/fcntl.h"
|
||||
|
||||
// Parsed command representation
|
||||
#define EXEC 1
|
||||
#define EXEC 1
|
||||
#define REDIR 2
|
||||
#define PIPE 3
|
||||
#define LIST 4
|
||||
#define BACK 5
|
||||
#define PIPE 3
|
||||
#define LIST 4
|
||||
#define BACK 5
|
||||
|
||||
#define MAXARGS 10
|
||||
|
||||
@@ -50,15 +49,15 @@ struct backcmd {
|
||||
struct cmd *cmd;
|
||||
};
|
||||
|
||||
int fork1(void); // Fork but panics on failure.
|
||||
void panic(char *);
|
||||
struct cmd *parsecmd(char *);
|
||||
void runcmd(struct cmd *) __attribute__((noreturn));
|
||||
// void handle_tab_completion(char *buf, int *i, int nbuf);
|
||||
// 尝试添加tab补全功能
|
||||
int fork1(void); // Fork but panics on failure.
|
||||
void panic(char*);
|
||||
struct cmd *parsecmd(char*);
|
||||
void runcmd(struct cmd*) __attribute__((noreturn));
|
||||
|
||||
// Execute cmd. Never returns.
|
||||
void runcmd(struct cmd *cmd) {
|
||||
void
|
||||
runcmd(struct cmd *cmd)
|
||||
{
|
||||
int p[2];
|
||||
struct backcmd *bcmd;
|
||||
struct execcmd *ecmd;
|
||||
@@ -66,25 +65,25 @@ void runcmd(struct cmd *cmd) {
|
||||
struct pipecmd *pcmd;
|
||||
struct redircmd *rcmd;
|
||||
|
||||
if (cmd == 0)
|
||||
if(cmd == 0)
|
||||
exit(1);
|
||||
|
||||
switch (cmd->type) {
|
||||
switch(cmd->type){
|
||||
default:
|
||||
panic("runcmd");
|
||||
|
||||
case EXEC:
|
||||
ecmd = (struct execcmd *)cmd;
|
||||
if (ecmd->argv[0] == 0)
|
||||
ecmd = (struct execcmd*)cmd;
|
||||
if(ecmd->argv[0] == 0)
|
||||
exit(1);
|
||||
exec(ecmd->argv[0], ecmd->argv);
|
||||
fprintf(2, "exec %s failed\n", ecmd->argv[0]);
|
||||
break;
|
||||
|
||||
case REDIR:
|
||||
rcmd = (struct redircmd *)cmd;
|
||||
rcmd = (struct redircmd*)cmd;
|
||||
close(rcmd->fd);
|
||||
if (open(rcmd->file, rcmd->mode) < 0) {
|
||||
if(open(rcmd->file, rcmd->mode) < 0){
|
||||
fprintf(2, "open %s failed\n", rcmd->file);
|
||||
exit(1);
|
||||
}
|
||||
@@ -92,25 +91,25 @@ void runcmd(struct cmd *cmd) {
|
||||
break;
|
||||
|
||||
case LIST:
|
||||
lcmd = (struct listcmd *)cmd;
|
||||
if (fork1() == 0)
|
||||
lcmd = (struct listcmd*)cmd;
|
||||
if(fork1() == 0)
|
||||
runcmd(lcmd->left);
|
||||
wait(0);
|
||||
runcmd(lcmd->right);
|
||||
break;
|
||||
|
||||
case PIPE:
|
||||
pcmd = (struct pipecmd *)cmd;
|
||||
if (pipe(p) < 0)
|
||||
pcmd = (struct pipecmd*)cmd;
|
||||
if(pipe(p) < 0)
|
||||
panic("pipe");
|
||||
if (fork1() == 0) {
|
||||
if(fork1() == 0){
|
||||
close(1);
|
||||
dup(p[1]);
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
runcmd(pcmd->left);
|
||||
}
|
||||
if (fork1() == 0) {
|
||||
if(fork1() == 0){
|
||||
close(0);
|
||||
dup(p[0]);
|
||||
close(p[0]);
|
||||
@@ -124,82 +123,90 @@ void runcmd(struct cmd *cmd) {
|
||||
break;
|
||||
|
||||
case BACK:
|
||||
bcmd = (struct backcmd *)cmd;
|
||||
if (fork1() == 0)
|
||||
bcmd = (struct backcmd*)cmd;
|
||||
if(fork1() == 0)
|
||||
runcmd(bcmd->cmd);
|
||||
break;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int getcmd(char *buf, int nbuf) {
|
||||
int
|
||||
getcmd(char *buf, int nbuf)
|
||||
{
|
||||
write(2, "$ ", 2);
|
||||
memset(buf, 0, nbuf);
|
||||
gets(buf, nbuf);
|
||||
if (buf[0] == 0) // EOF
|
||||
if(buf[0] == 0) // EOF
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
static char buf[100];
|
||||
int fd;
|
||||
|
||||
// Ensure that three file descriptors are open.
|
||||
while ((fd = open("console", O_RDWR)) >= 0) {
|
||||
if (fd >= 3) {
|
||||
while((fd = open("console", O_RDWR)) >= 0){
|
||||
if(fd >= 3){
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Read and run input commands.
|
||||
while (getcmd(buf, sizeof(buf)) >= 0) {
|
||||
if (strcmp(buf, "exit\n") == 0) {
|
||||
exit(0);
|
||||
}
|
||||
if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') {
|
||||
while(getcmd(buf, sizeof(buf)) >= 0){
|
||||
if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
|
||||
// Chdir must be called by the parent, not the child.
|
||||
buf[strlen(buf) - 1] = 0; // chop \n
|
||||
if (chdir(buf + 3) < 0)
|
||||
fprintf(2, "cannot cd %s\n", buf + 3);
|
||||
buf[strlen(buf)-1] = 0; // chop \n
|
||||
if(chdir(buf+3) < 0)
|
||||
fprintf(2, "cannot cd %s\n", buf+3);
|
||||
continue;
|
||||
}
|
||||
if (fork1() == 0)
|
||||
if(fork1() == 0)
|
||||
runcmd(parsecmd(buf));
|
||||
wait(0);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void panic(char *s) {
|
||||
void
|
||||
panic(char *s)
|
||||
{
|
||||
fprintf(2, "%s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fork1(void) {
|
||||
int
|
||||
fork1(void)
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
if(pid == -1)
|
||||
panic("fork");
|
||||
return pid;
|
||||
}
|
||||
|
||||
// PAGEBREAK!
|
||||
// Constructors
|
||||
//PAGEBREAK!
|
||||
// Constructors
|
||||
|
||||
struct cmd *execcmd(void) {
|
||||
struct cmd*
|
||||
execcmd(void)
|
||||
{
|
||||
struct execcmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->type = EXEC;
|
||||
return (struct cmd *)cmd;
|
||||
return (struct cmd*)cmd;
|
||||
}
|
||||
|
||||
struct cmd *redircmd(struct cmd *subcmd, char *file, char *efile, int mode,
|
||||
int fd) {
|
||||
struct cmd*
|
||||
redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
|
||||
{
|
||||
struct redircmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
@@ -210,10 +217,12 @@ struct cmd *redircmd(struct cmd *subcmd, char *file, char *efile, int mode,
|
||||
cmd->efile = efile;
|
||||
cmd->mode = mode;
|
||||
cmd->fd = fd;
|
||||
return (struct cmd *)cmd;
|
||||
return (struct cmd*)cmd;
|
||||
}
|
||||
|
||||
struct cmd *pipecmd(struct cmd *left, struct cmd *right) {
|
||||
struct cmd*
|
||||
pipecmd(struct cmd *left, struct cmd *right)
|
||||
{
|
||||
struct pipecmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
@@ -221,10 +230,12 @@ struct cmd *pipecmd(struct cmd *left, struct cmd *right) {
|
||||
cmd->type = PIPE;
|
||||
cmd->left = left;
|
||||
cmd->right = right;
|
||||
return (struct cmd *)cmd;
|
||||
return (struct cmd*)cmd;
|
||||
}
|
||||
|
||||
struct cmd *listcmd(struct cmd *left, struct cmd *right) {
|
||||
struct cmd*
|
||||
listcmd(struct cmd *left, struct cmd *right)
|
||||
{
|
||||
struct listcmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
@@ -232,35 +243,39 @@ struct cmd *listcmd(struct cmd *left, struct cmd *right) {
|
||||
cmd->type = LIST;
|
||||
cmd->left = left;
|
||||
cmd->right = right;
|
||||
return (struct cmd *)cmd;
|
||||
return (struct cmd*)cmd;
|
||||
}
|
||||
|
||||
struct cmd *backcmd(struct cmd *subcmd) {
|
||||
struct cmd*
|
||||
backcmd(struct cmd *subcmd)
|
||||
{
|
||||
struct backcmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->type = BACK;
|
||||
cmd->cmd = subcmd;
|
||||
return (struct cmd *)cmd;
|
||||
return (struct cmd*)cmd;
|
||||
}
|
||||
// PAGEBREAK!
|
||||
// Parsing
|
||||
//PAGEBREAK!
|
||||
// Parsing
|
||||
|
||||
char whitespace[] = " \t\r\n\v";
|
||||
char symbols[] = "<|>&;()";
|
||||
|
||||
int gettoken(char **ps, char *es, char **q, char **eq) {
|
||||
int
|
||||
gettoken(char **ps, char *es, char **q, char **eq)
|
||||
{
|
||||
char *s;
|
||||
int ret;
|
||||
|
||||
s = *ps;
|
||||
while (s < es && strchr(whitespace, *s))
|
||||
while(s < es && strchr(whitespace, *s))
|
||||
s++;
|
||||
if (q)
|
||||
if(q)
|
||||
*q = s;
|
||||
ret = *s;
|
||||
switch (*s) {
|
||||
switch(*s){
|
||||
case 0:
|
||||
break;
|
||||
case '|':
|
||||
@@ -273,49 +288,53 @@ int gettoken(char **ps, char *es, char **q, char **eq) {
|
||||
break;
|
||||
case '>':
|
||||
s++;
|
||||
if (*s == '>') {
|
||||
if(*s == '>'){
|
||||
ret = '+';
|
||||
s++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = 'a';
|
||||
while (s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
|
||||
while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
if (eq)
|
||||
if(eq)
|
||||
*eq = s;
|
||||
|
||||
while (s < es && strchr(whitespace, *s))
|
||||
while(s < es && strchr(whitespace, *s))
|
||||
s++;
|
||||
*ps = s;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int peek(char **ps, char *es, char *toks) {
|
||||
int
|
||||
peek(char **ps, char *es, char *toks)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = *ps;
|
||||
while (s < es && strchr(whitespace, *s))
|
||||
while(s < es && strchr(whitespace, *s))
|
||||
s++;
|
||||
*ps = s;
|
||||
return *s && strchr(toks, *s);
|
||||
}
|
||||
|
||||
struct cmd *parseline(char **, char *);
|
||||
struct cmd *parsepipe(char **, char *);
|
||||
struct cmd *parseexec(char **, char *);
|
||||
struct cmd *nulterminate(struct cmd *);
|
||||
struct cmd *parseline(char**, char*);
|
||||
struct cmd *parsepipe(char**, char*);
|
||||
struct cmd *parseexec(char**, char*);
|
||||
struct cmd *nulterminate(struct cmd*);
|
||||
|
||||
struct cmd *parsecmd(char *s) {
|
||||
struct cmd*
|
||||
parsecmd(char *s)
|
||||
{
|
||||
char *es;
|
||||
struct cmd *cmd;
|
||||
|
||||
es = s + strlen(s);
|
||||
cmd = parseline(&s, es);
|
||||
peek(&s, es, "");
|
||||
if (s != es) {
|
||||
if(s != es){
|
||||
fprintf(2, "leftovers: %s\n", s);
|
||||
panic("syntax");
|
||||
}
|
||||
@@ -323,92 +342,102 @@ struct cmd *parsecmd(char *s) {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct cmd *parseline(char **ps, char *es) {
|
||||
struct cmd*
|
||||
parseline(char **ps, char *es)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
cmd = parsepipe(ps, es);
|
||||
while (peek(ps, es, "&")) {
|
||||
while(peek(ps, es, "&")){
|
||||
gettoken(ps, es, 0, 0);
|
||||
cmd = backcmd(cmd);
|
||||
}
|
||||
if (peek(ps, es, ";")) {
|
||||
if(peek(ps, es, ";")){
|
||||
gettoken(ps, es, 0, 0);
|
||||
cmd = listcmd(cmd, parseline(ps, es));
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct cmd *parsepipe(char **ps, char *es) {
|
||||
struct cmd*
|
||||
parsepipe(char **ps, char *es)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
cmd = parseexec(ps, es);
|
||||
if (peek(ps, es, "|")) {
|
||||
if(peek(ps, es, "|")){
|
||||
gettoken(ps, es, 0, 0);
|
||||
cmd = pipecmd(cmd, parsepipe(ps, es));
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct cmd *parseredirs(struct cmd *cmd, char **ps, char *es) {
|
||||
struct cmd*
|
||||
parseredirs(struct cmd *cmd, char **ps, char *es)
|
||||
{
|
||||
int tok;
|
||||
char *q, *eq;
|
||||
|
||||
while (peek(ps, es, "<>")) {
|
||||
while(peek(ps, es, "<>")){
|
||||
tok = gettoken(ps, es, 0, 0);
|
||||
if (gettoken(ps, es, &q, &eq) != 'a')
|
||||
if(gettoken(ps, es, &q, &eq) != 'a')
|
||||
panic("missing file for redirection");
|
||||
switch (tok) {
|
||||
switch(tok){
|
||||
case '<':
|
||||
cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
|
||||
break;
|
||||
case '>':
|
||||
cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE | O_TRUNC, 1);
|
||||
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE|O_TRUNC, 1);
|
||||
break;
|
||||
case '+': // >>
|
||||
cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE, 1);
|
||||
case '+': // >>
|
||||
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct cmd *parseblock(char **ps, char *es) {
|
||||
struct cmd*
|
||||
parseblock(char **ps, char *es)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
if (!peek(ps, es, "("))
|
||||
if(!peek(ps, es, "("))
|
||||
panic("parseblock");
|
||||
gettoken(ps, es, 0, 0);
|
||||
cmd = parseline(ps, es);
|
||||
if (!peek(ps, es, ")"))
|
||||
if(!peek(ps, es, ")"))
|
||||
panic("syntax - missing )");
|
||||
gettoken(ps, es, 0, 0);
|
||||
cmd = parseredirs(cmd, ps, es);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct cmd *parseexec(char **ps, char *es) {
|
||||
struct cmd*
|
||||
parseexec(char **ps, char *es)
|
||||
{
|
||||
char *q, *eq;
|
||||
int tok, argc;
|
||||
struct execcmd *cmd;
|
||||
struct cmd *ret;
|
||||
|
||||
if (peek(ps, es, "("))
|
||||
if(peek(ps, es, "("))
|
||||
return parseblock(ps, es);
|
||||
|
||||
ret = execcmd();
|
||||
cmd = (struct execcmd *)ret;
|
||||
cmd = (struct execcmd*)ret;
|
||||
|
||||
argc = 0;
|
||||
ret = parseredirs(ret, ps, es);
|
||||
while (!peek(ps, es, "|)&;")) {
|
||||
if ((tok = gettoken(ps, es, &q, &eq)) == 0)
|
||||
while(!peek(ps, es, "|)&;")){
|
||||
if((tok=gettoken(ps, es, &q, &eq)) == 0)
|
||||
break;
|
||||
if (tok != 'a')
|
||||
if(tok != 'a')
|
||||
panic("syntax");
|
||||
cmd->argv[argc] = q;
|
||||
cmd->eargv[argc] = eq;
|
||||
argc++;
|
||||
if (argc >= MAXARGS)
|
||||
if(argc >= MAXARGS)
|
||||
panic("too many args");
|
||||
ret = parseredirs(ret, ps, es);
|
||||
}
|
||||
@@ -418,7 +447,9 @@ struct cmd *parseexec(char **ps, char *es) {
|
||||
}
|
||||
|
||||
// NUL-terminate all the counted strings.
|
||||
struct cmd *nulterminate(struct cmd *cmd) {
|
||||
struct cmd*
|
||||
nulterminate(struct cmd *cmd)
|
||||
{
|
||||
int i;
|
||||
struct backcmd *bcmd;
|
||||
struct execcmd *ecmd;
|
||||
@@ -426,36 +457,36 @@ struct cmd *nulterminate(struct cmd *cmd) {
|
||||
struct pipecmd *pcmd;
|
||||
struct redircmd *rcmd;
|
||||
|
||||
if (cmd == 0)
|
||||
if(cmd == 0)
|
||||
return 0;
|
||||
|
||||
switch (cmd->type) {
|
||||
switch(cmd->type){
|
||||
case EXEC:
|
||||
ecmd = (struct execcmd *)cmd;
|
||||
for (i = 0; ecmd->argv[i]; i++)
|
||||
ecmd = (struct execcmd*)cmd;
|
||||
for(i=0; ecmd->argv[i]; i++)
|
||||
*ecmd->eargv[i] = 0;
|
||||
break;
|
||||
|
||||
case REDIR:
|
||||
rcmd = (struct redircmd *)cmd;
|
||||
rcmd = (struct redircmd*)cmd;
|
||||
nulterminate(rcmd->cmd);
|
||||
*rcmd->efile = 0;
|
||||
break;
|
||||
|
||||
case PIPE:
|
||||
pcmd = (struct pipecmd *)cmd;
|
||||
pcmd = (struct pipecmd*)cmd;
|
||||
nulterminate(pcmd->left);
|
||||
nulterminate(pcmd->right);
|
||||
break;
|
||||
|
||||
case LIST:
|
||||
lcmd = (struct listcmd *)cmd;
|
||||
lcmd = (struct listcmd*)cmd;
|
||||
nulterminate(lcmd->left);
|
||||
nulterminate(lcmd->right);
|
||||
break;
|
||||
|
||||
case BACK:
|
||||
bcmd = (struct backcmd *)cmd;
|
||||
bcmd = (struct backcmd*)cmd;
|
||||
nulterminate(bcmd->cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
119
user/ulib.c
119
user/ulib.c
@@ -1,133 +1,139 @@
|
||||
#include "kernel/fcntl.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/stat.h"
|
||||
#include "kernel/fcntl.h"
|
||||
#ifdef LAB_PGTBL
|
||||
#include "kernel/riscv.h"
|
||||
#include "kernel/memlayout.h"
|
||||
#endif
|
||||
#include "user/user.h"
|
||||
|
||||
|
||||
//
|
||||
// wrapper so that it's OK if main() does not call exit().
|
||||
//
|
||||
void _main() {
|
||||
void
|
||||
start()
|
||||
{
|
||||
extern int main();
|
||||
main();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *strcpy(char *s, const char *t) {
|
||||
char*
|
||||
strcpy(char *s, const char *t)
|
||||
{
|
||||
char *os;
|
||||
|
||||
os = s;
|
||||
while ((*s++ = *t++) != 0)
|
||||
while((*s++ = *t++) != 0)
|
||||
;
|
||||
return os;
|
||||
}
|
||||
|
||||
char *strncpy(char *s, const char *t, int n) {
|
||||
char *os;
|
||||
|
||||
os = s;
|
||||
if (n <= 0)
|
||||
return os;
|
||||
while (--n > 0 && (*s++ = *t++) != 0)
|
||||
;
|
||||
while (n-- > 0)
|
||||
*s++ = 0;
|
||||
return os;
|
||||
}
|
||||
|
||||
int strcmp(const char *p, const char *q) {
|
||||
while (*p && *p == *q)
|
||||
int
|
||||
strcmp(const char *p, const char *q)
|
||||
{
|
||||
while(*p && *p == *q)
|
||||
p++, q++;
|
||||
return (uchar)*p - (uchar)*q;
|
||||
}
|
||||
|
||||
int strncmp(const char *p, const char *q, int n) {
|
||||
while (n > 0 && *p && *p == *q)
|
||||
p++, q++, n--;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
return (uchar)*p - (uchar)*q;
|
||||
}
|
||||
|
||||
uint strlen(const char *s) {
|
||||
uint
|
||||
strlen(const char *s)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; s[n]; n++)
|
||||
for(n = 0; s[n]; n++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
void *memset(void *dst, int c, uint n) {
|
||||
char *cdst = (char *)dst;
|
||||
void*
|
||||
memset(void *dst, int c, uint n)
|
||||
{
|
||||
char *cdst = (char *) dst;
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
for(i = 0; i < n; i++){
|
||||
cdst[i] = c;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *strchr(const char *s, char c) {
|
||||
for (; *s; s++)
|
||||
if (*s == c)
|
||||
return (char *)s;
|
||||
char*
|
||||
strchr(const char *s, char c)
|
||||
{
|
||||
for(; *s; s++)
|
||||
if(*s == c)
|
||||
return (char*)s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *gets(char *buf, int max) {
|
||||
char*
|
||||
gets(char *buf, int max)
|
||||
{
|
||||
int i, cc;
|
||||
char c;
|
||||
|
||||
for (i = 0; i + 1 < max;) {
|
||||
for(i=0; i+1 < max; ){
|
||||
cc = read(0, &c, 1);
|
||||
if (cc < 1)
|
||||
if(cc < 1)
|
||||
break;
|
||||
buf[i++] = c;
|
||||
if (c == '\n' || c == '\r')
|
||||
if(c == '\n' || c == '\r')
|
||||
break;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int stat(const char *n, struct stat *st) {
|
||||
int
|
||||
stat(const char *n, struct stat *st)
|
||||
{
|
||||
int fd;
|
||||
int r;
|
||||
|
||||
fd = open(n, O_RDONLY);
|
||||
if (fd < 0)
|
||||
if(fd < 0)
|
||||
return -1;
|
||||
r = fstat(fd, st);
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int atoi(const char *s) {
|
||||
int
|
||||
atoi(const char *s)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
while ('0' <= *s && *s <= '9')
|
||||
n = n * 10 + *s++ - '0';
|
||||
while('0' <= *s && *s <= '9')
|
||||
n = n*10 + *s++ - '0';
|
||||
return n;
|
||||
}
|
||||
|
||||
void *memmove(void *vdst, const void *vsrc, int n) {
|
||||
void*
|
||||
memmove(void *vdst, const void *vsrc, int n)
|
||||
{
|
||||
char *dst;
|
||||
const char *src;
|
||||
|
||||
dst = vdst;
|
||||
src = vsrc;
|
||||
if (src > dst) {
|
||||
while (n-- > 0)
|
||||
while(n-- > 0)
|
||||
*dst++ = *src++;
|
||||
} else {
|
||||
dst += n;
|
||||
src += n;
|
||||
while (n-- > 0)
|
||||
while(n-- > 0)
|
||||
*--dst = *--src;
|
||||
}
|
||||
return vdst;
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, uint n) {
|
||||
int
|
||||
memcmp(const void *s1, const void *s2, uint n)
|
||||
{
|
||||
const char *p1 = s1, *p2 = s2;
|
||||
while (n-- > 0) {
|
||||
if (*p1 != *p2) {
|
||||
@@ -139,6 +145,17 @@ int memcmp(const void *s1, const void *s2, uint n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *memcpy(void *dst, const void *src, uint n) {
|
||||
void *
|
||||
memcpy(void *dst, const void *src, uint n)
|
||||
{
|
||||
return memmove(dst, src, n);
|
||||
}
|
||||
|
||||
#ifdef LAB_PGTBL
|
||||
int
|
||||
ugetpid(void)
|
||||
{
|
||||
struct usyscall *u = (struct usyscall *)USYSCALL;
|
||||
return u->pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
79
user/user.h
79
user/user.h
@@ -1,47 +1,62 @@
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/sysinfo.h"
|
||||
#ifdef LAB_MMAP
|
||||
typedef unsigned long size_t;
|
||||
typedef long int off_t;
|
||||
#endif
|
||||
struct stat;
|
||||
|
||||
// system calls
|
||||
int fork(void);
|
||||
int exit(int) __attribute__((noreturn));
|
||||
int wait(int *);
|
||||
int pipe(int *);
|
||||
int write(int, const void *, int);
|
||||
int read(int, void *, int);
|
||||
int wait(int*);
|
||||
int pipe(int*);
|
||||
int write(int, const void*, int);
|
||||
int read(int, void*, int);
|
||||
int close(int);
|
||||
int kill(int);
|
||||
int exec(const char *, char **);
|
||||
int open(const char *, int);
|
||||
int mknod(const char *, short, short);
|
||||
int unlink(const char *);
|
||||
int fstat(int fd, struct stat *);
|
||||
int link(const char *, const char *);
|
||||
int mkdir(const char *);
|
||||
int chdir(const char *);
|
||||
int exec(const char*, char**);
|
||||
int open(const char*, int);
|
||||
int mknod(const char*, short, short);
|
||||
int unlink(const char*);
|
||||
int fstat(int fd, struct stat*);
|
||||
int link(const char*, const char*);
|
||||
int mkdir(const char*);
|
||||
int chdir(const char*);
|
||||
int dup(int);
|
||||
int getpid(void);
|
||||
char *sbrk(int);
|
||||
char* sbrk(int);
|
||||
int sleep(int);
|
||||
int uptime(void);
|
||||
int trace(int);
|
||||
int sysinfo(struct sysinfo*);
|
||||
#ifdef LAB_NET
|
||||
int bind(uint32);
|
||||
int unbind(uint32);
|
||||
int send(uint32, uint32, uint32, char *, uint32);
|
||||
int recv(uint32, uint32*, uint32*, char *, uint32);
|
||||
#endif
|
||||
#ifdef LAB_PGTBL
|
||||
int ugetpid(void);
|
||||
uint64 pgpte(void*);
|
||||
void kpgtbl(void);
|
||||
int pgaccess(void *base, int len, void *mask);
|
||||
#endif
|
||||
|
||||
// ulib.c
|
||||
int stat(const char *, struct stat *);
|
||||
char *strcpy(char *, const char *);
|
||||
char *strncpy(char *, const char *, int);
|
||||
void *memmove(void *, const void *, int);
|
||||
char *strchr(const char *, char c);
|
||||
int strcmp(const char *, const char *);
|
||||
int strncmp(const char *, const char *, int);
|
||||
void fprintf(int, const char *, ...);
|
||||
void printf(const char *, ...);
|
||||
char *gets(char *, int max);
|
||||
uint strlen(const char *);
|
||||
void *memset(void *, int, uint);
|
||||
void *malloc(uint);
|
||||
void free(void *);
|
||||
int atoi(const char *);
|
||||
int stat(const char*, struct stat*);
|
||||
char* strcpy(char*, const char*);
|
||||
void *memmove(void*, const void*, int);
|
||||
char* strchr(const char*, char c);
|
||||
int strcmp(const char*, const char*);
|
||||
void fprintf(int, const char*, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
void printf(const char*, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
char* gets(char*, int max);
|
||||
uint strlen(const char*);
|
||||
void* memset(void*, int, uint);
|
||||
int atoi(const char*);
|
||||
int memcmp(const void *, const void *, uint);
|
||||
void *memcpy(void *, const void *, uint);
|
||||
#ifdef LAB_LOCK
|
||||
int statistics(void*, int);
|
||||
#endif
|
||||
|
||||
// umalloc.c
|
||||
void* malloc(uint);
|
||||
void free(void*);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY( _main )
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
@@ -15,9 +13,14 @@ SECTIONS
|
||||
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
||||
. = ALIGN(16);
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(0x1000);
|
||||
}
|
||||
|
||||
.eh_frame : {
|
||||
*(.eh_frame)
|
||||
*(.eh_frame.*)
|
||||
}
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
.data : {
|
||||
. = ALIGN(16);
|
||||
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
||||
|
||||
121
user/usertests.c
121
user/usertests.c
@@ -32,9 +32,10 @@ char buf[BUFSZ];
|
||||
void
|
||||
copyin(char *s)
|
||||
{
|
||||
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
|
||||
uint64 addrs[] = { 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||
0xffffffffffffffff };
|
||||
|
||||
for(int ai = 0; ai < 2; ai++){
|
||||
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||
uint64 addr = addrs[ai];
|
||||
|
||||
int fd = open("copyin1", O_CREATE|O_WRONLY);
|
||||
@@ -44,7 +45,7 @@ copyin(char *s)
|
||||
}
|
||||
int n = write(fd, (void*)addr, 8192);
|
||||
if(n >= 0){
|
||||
printf("write(fd, %p, 8192) returned %d, not -1\n", addr, n);
|
||||
printf("write(fd, %p, 8192) returned %d, not -1\n", (void*)addr, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
@@ -52,7 +53,7 @@ copyin(char *s)
|
||||
|
||||
n = write(1, (char*)addr, 8192);
|
||||
if(n > 0){
|
||||
printf("write(1, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
||||
printf("write(1, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ copyin(char *s)
|
||||
}
|
||||
n = write(fds[1], (char*)addr, 8192);
|
||||
if(n > 0){
|
||||
printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
||||
printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fds[0]);
|
||||
@@ -76,9 +77,10 @@ copyin(char *s)
|
||||
void
|
||||
copyout(char *s)
|
||||
{
|
||||
uint64 addrs[] = { 0LL, 0x80000000LL, 0xffffffffffffffff };
|
||||
uint64 addrs[] = { 0LL, 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||
0xffffffffffffffff };
|
||||
|
||||
for(int ai = 0; ai < 2; ai++){
|
||||
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||
uint64 addr = addrs[ai];
|
||||
|
||||
int fd = open("README", 0);
|
||||
@@ -88,7 +90,7 @@ copyout(char *s)
|
||||
}
|
||||
int n = read(fd, (void*)addr, 8192);
|
||||
if(n > 0){
|
||||
printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
||||
printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
@@ -105,7 +107,7 @@ copyout(char *s)
|
||||
}
|
||||
n = read(fds[0], (void*)addr, 8192);
|
||||
if(n > 0){
|
||||
printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n);
|
||||
printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", (void*)addr, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fds[0]);
|
||||
@@ -117,14 +119,15 @@ copyout(char *s)
|
||||
void
|
||||
copyinstr1(char *s)
|
||||
{
|
||||
uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff };
|
||||
uint64 addrs[] = { 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||
0xffffffffffffffff };
|
||||
|
||||
for(int ai = 0; ai < 2; ai++){
|
||||
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||
uint64 addr = addrs[ai];
|
||||
|
||||
int fd = open((char *)addr, O_CREATE|O_WRONLY);
|
||||
if(fd >= 0){
|
||||
printf("open(%p) returned %d, not -1\n", addr, fd);
|
||||
printf("open(%p) returned %d, not -1\n", (void*)addr, fd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -264,7 +267,7 @@ rwsbrk()
|
||||
}
|
||||
n = write(fd, (void*)(a+4096), 1024);
|
||||
if(n >= 0){
|
||||
printf("write(fd, %p, 1024) returned %d, not -1\n", a+4096, n);
|
||||
printf("write(fd, %p, 1024) returned %d, not -1\n", (void*)a+4096, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
@@ -277,7 +280,7 @@ rwsbrk()
|
||||
}
|
||||
n = read(fd, (void*)(a+4096), 10);
|
||||
if(n >= 0){
|
||||
printf("read(fd, %p, 10) returned %d, not -1\n", a+4096, n);
|
||||
printf("read(fd, %p, 10) returned %d, not -1\n", (void*)a+4096, n);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
@@ -589,7 +592,7 @@ writebig(char *s)
|
||||
for(i = 0; i < MAXFILE; i++){
|
||||
((int*)buf)[0] = i;
|
||||
if(write(fd, buf, BSIZE) != BSIZE){
|
||||
printf("%s: error: write big file failed\n", s, i);
|
||||
printf("%s: error: write big file failed i=%d\n", s, i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -606,7 +609,7 @@ writebig(char *s)
|
||||
for(;;){
|
||||
i = read(fd, buf, BSIZE);
|
||||
if(i == 0){
|
||||
if(n == MAXFILE - 1){
|
||||
if(n != MAXFILE){
|
||||
printf("%s: read only %d blocks from big", s, n);
|
||||
exit(1);
|
||||
}
|
||||
@@ -773,7 +776,7 @@ pipe1(char *s)
|
||||
cc = sizeof(buf);
|
||||
}
|
||||
if(total != N * SZ){
|
||||
printf("%s: pipe1 oops 3 total %d\n", total);
|
||||
printf("%s: pipe1 oops 3 total %d\n", s, total);
|
||||
exit(1);
|
||||
}
|
||||
close(fds[0]);
|
||||
@@ -1069,7 +1072,7 @@ mem(char *s)
|
||||
}
|
||||
m1 = malloc(1024*20);
|
||||
if(m1 == 0){
|
||||
printf("couldn't allocate mem?!!\n", s);
|
||||
printf("%s: couldn't allocate mem?!!\n", s);
|
||||
exit(1);
|
||||
}
|
||||
free(m1);
|
||||
@@ -1161,14 +1164,14 @@ fourfiles(char *s)
|
||||
|
||||
pid = fork();
|
||||
if(pid < 0){
|
||||
printf("fork failed\n", s);
|
||||
printf("%s: fork failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(pid == 0){
|
||||
fd = open(fname, O_CREATE | O_RDWR);
|
||||
if(fd < 0){
|
||||
printf("create failed\n", s);
|
||||
printf("%s: create failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1197,7 +1200,7 @@ fourfiles(char *s)
|
||||
while((n = read(fd, buf, sizeof(buf))) > 0){
|
||||
for(j = 0; j < n; j++){
|
||||
if(buf[j] != '0'+i){
|
||||
printf("wrong char\n", s);
|
||||
printf("%s: wrong char\n", s);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1226,7 @@ createdelete(char *s)
|
||||
for(pi = 0; pi < NCHILD; pi++){
|
||||
pid = fork();
|
||||
if(pid < 0){
|
||||
printf("fork failed\n", s);
|
||||
printf("%s: fork failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1277,7 +1280,7 @@ createdelete(char *s)
|
||||
|
||||
for(i = 0; i < N; i++){
|
||||
for(pi = 0; pi < NCHILD; pi++){
|
||||
name[0] = 'p' + i;
|
||||
name[0] = 'p' + pi;
|
||||
name[1] = '0' + i;
|
||||
unlink(name);
|
||||
}
|
||||
@@ -1544,7 +1547,7 @@ subdir(char *s)
|
||||
}
|
||||
|
||||
if(mkdir("/dd/dd") != 0){
|
||||
printf("subdir mkdir dd/dd failed\n", s);
|
||||
printf("%s: subdir mkdir dd/dd failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1569,7 +1572,7 @@ subdir(char *s)
|
||||
close(fd);
|
||||
|
||||
if(link("dd/dd/ff", "dd/dd/ffff") != 0){
|
||||
printf("link dd/dd/ff dd/dd/ffff failed\n", s);
|
||||
printf("%s: link dd/dd/ff dd/dd/ffff failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1591,7 +1594,7 @@ subdir(char *s)
|
||||
exit(1);
|
||||
}
|
||||
if(chdir("dd/../../../dd") != 0){
|
||||
printf("chdir dd/../../dd failed\n", s);
|
||||
printf("%s: chdir dd/../../../dd failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
if(chdir("./..") != 0){
|
||||
@@ -2034,7 +2037,7 @@ sbrkbasic(char *s)
|
||||
for(i = 0; i < 5000; i++){
|
||||
b = sbrk(1);
|
||||
if(b != a){
|
||||
printf("%s: sbrk test failed %d %x %x\n", s, i, a, b);
|
||||
printf("%s: sbrk test failed %d %p %p\n", s, i, a, b);
|
||||
exit(1);
|
||||
}
|
||||
*b = 1;
|
||||
@@ -2092,7 +2095,7 @@ sbrkmuch(char *s)
|
||||
}
|
||||
c = sbrk(0);
|
||||
if(c != a - PGSIZE){
|
||||
printf("%s: sbrk deallocation produced wrong address, a %x c %x\n", s, a, c);
|
||||
printf("%s: sbrk deallocation produced wrong address, a %p c %p\n", s, a, c);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -2100,7 +2103,7 @@ sbrkmuch(char *s)
|
||||
a = sbrk(0);
|
||||
c = sbrk(PGSIZE);
|
||||
if(c != a || sbrk(0) != a + PGSIZE){
|
||||
printf("%s: sbrk re-allocation failed, a %x c %x\n", s, a, c);
|
||||
printf("%s: sbrk re-allocation failed, a %p c %p\n", s, a, c);
|
||||
exit(1);
|
||||
}
|
||||
if(*lastaddr == 99){
|
||||
@@ -2112,7 +2115,7 @@ sbrkmuch(char *s)
|
||||
a = sbrk(0);
|
||||
c = sbrk(-(sbrk(0) - oldbrk));
|
||||
if(c != a){
|
||||
printf("%s: sbrk downsize failed, a %x c %x\n", s, a, c);
|
||||
printf("%s: sbrk downsize failed, a %p c %p\n", s, a, c);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -2131,7 +2134,7 @@ kernmem(char *s)
|
||||
exit(1);
|
||||
}
|
||||
if(pid == 0){
|
||||
printf("%s: oops could read %x = %x\n", s, a, *a);
|
||||
printf("%s: oops could read %p = %x\n", s, a, *a);
|
||||
exit(1);
|
||||
}
|
||||
int xstatus;
|
||||
@@ -2155,7 +2158,7 @@ MAXVAplus(char *s)
|
||||
}
|
||||
if(pid == 0){
|
||||
*(char*)a = 99;
|
||||
printf("%s: oops wrote %x\n", s, a);
|
||||
printf("%s: oops wrote %p\n", s, (void*)a);
|
||||
exit(1);
|
||||
}
|
||||
int xstatus;
|
||||
@@ -2307,9 +2310,14 @@ bigargtest(char *s)
|
||||
if(pid == 0){
|
||||
static char *args[MAXARG];
|
||||
int i;
|
||||
char big[400];
|
||||
memset(big, ' ', sizeof(big));
|
||||
big[sizeof(big)-1] = '\0';
|
||||
for(i = 0; i < MAXARG-1; i++)
|
||||
args[i] = "bigargs test: failed\n ";
|
||||
args[i] = big;
|
||||
args[MAXARG-1] = 0;
|
||||
// this exec() should fail (and return) because the
|
||||
// arguments are too large.
|
||||
exec("echo", args);
|
||||
fd = open("bigarg-ok", O_CREATE);
|
||||
close(fd);
|
||||
@@ -2406,9 +2414,9 @@ stacktest(char *s)
|
||||
pid = fork();
|
||||
if(pid == 0) {
|
||||
char *sp = (char *) r_sp();
|
||||
sp -= PGSIZE;
|
||||
sp -= USERSTACK*PGSIZE;
|
||||
// the *sp should cause a trap.
|
||||
printf("%s: stacktest: read below stack %p\n", s, *sp);
|
||||
printf("%s: stacktest: read below stack %d\n", s, *sp);
|
||||
exit(1);
|
||||
} else if(pid < 0){
|
||||
printf("%s: fork failed\n", s);
|
||||
@@ -2421,27 +2429,34 @@ stacktest(char *s)
|
||||
exit(xstatus);
|
||||
}
|
||||
|
||||
// check that writes to text segment fault
|
||||
// check that writes to a few forbidden addresses
|
||||
// cause a fault, e.g. process's text and TRAMPOLINE.
|
||||
void
|
||||
textwrite(char *s)
|
||||
nowrite(char *s)
|
||||
{
|
||||
int pid;
|
||||
int xstatus;
|
||||
uint64 addrs[] = { 0, 0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
|
||||
0xffffffffffffffff };
|
||||
|
||||
pid = fork();
|
||||
if(pid == 0) {
|
||||
volatile int *addr = (int *) 0;
|
||||
*addr = 10;
|
||||
exit(1);
|
||||
} else if(pid < 0){
|
||||
printf("%s: fork failed\n", s);
|
||||
exit(1);
|
||||
for(int ai = 0; ai < sizeof(addrs)/sizeof(addrs[0]); ai++){
|
||||
pid = fork();
|
||||
if(pid == 0) {
|
||||
volatile int *addr = (int *) addrs[ai];
|
||||
*addr = 10;
|
||||
printf("%s: write to %p did not fail!\n", s, addr);
|
||||
exit(0);
|
||||
} else if(pid < 0){
|
||||
printf("%s: fork failed\n", s);
|
||||
exit(1);
|
||||
}
|
||||
wait(&xstatus);
|
||||
if(xstatus == 0){
|
||||
// kernel did not kill child!
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
wait(&xstatus);
|
||||
if(xstatus == -1) // kernel killed child?
|
||||
exit(0);
|
||||
else
|
||||
exit(xstatus);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// regression test. copyin(), copyout(), and copyinstr() used to cast
|
||||
@@ -2629,7 +2644,7 @@ struct test {
|
||||
{bigargtest, "bigargtest"},
|
||||
{argptest, "argptest"},
|
||||
{stacktest, "stacktest"},
|
||||
{textwrite, "textwrite"},
|
||||
{nowrite, "nowrite"},
|
||||
{pgbug, "pgbug" },
|
||||
{sbrkbugs, "sbrkbugs" },
|
||||
{sbrklast, "sbrklast"},
|
||||
@@ -2666,7 +2681,7 @@ bigdir(char *s)
|
||||
name[2] = '0' + (i % 64);
|
||||
name[3] = '\0';
|
||||
if(link("bd", name) != 0){
|
||||
printf("%s: bigdir link(bd, %s) failed\n", s, name);
|
||||
printf("%s: bigdir i=%d link(bd, %s) failed\n", s, i, name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -2868,7 +2883,7 @@ diskfull(char *s)
|
||||
|
||||
// this mkdir() is expected to fail.
|
||||
if(mkdir("diskfulldir") == 0)
|
||||
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n");
|
||||
printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n", s);
|
||||
|
||||
unlink("diskfulldir");
|
||||
|
||||
|
||||
@@ -36,5 +36,10 @@ entry("getpid");
|
||||
entry("sbrk");
|
||||
entry("sleep");
|
||||
entry("uptime");
|
||||
entry("trace");
|
||||
entry("sysinfo");
|
||||
entry("bind");
|
||||
entry("unbind");
|
||||
entry("send");
|
||||
entry("recv");
|
||||
entry("pgpte");
|
||||
entry("kpgtbl");
|
||||
entry("pgaccess");
|
||||
|
||||
Reference in New Issue
Block a user