i/o redirection in sh
better parsing of sh commands (copied from jos sh) cat: read from 1 if no args sbrk system call, but untested getpid system call moved locks in keyboard intr, but why do we get intr w. null characters from keyboard?
This commit is contained in:
parent
f18ab5c04e
commit
8b58e81077
15 changed files with 433 additions and 74 deletions
8
Notes
8
Notes
|
@ -131,3 +131,11 @@ maybe get rid of per-proc gdt and ts
|
||||||
one per cpu
|
one per cpu
|
||||||
refresh it when needed
|
refresh it when needed
|
||||||
setupsegs(proc *)
|
setupsegs(proc *)
|
||||||
|
|
||||||
|
why do we get 0 characters from keyboard?
|
||||||
|
are the locks in the right place in keyboardintr?
|
||||||
|
|
||||||
|
sh: support pipes? leave it for the class?
|
||||||
|
sh: dynamic memory allocation?
|
||||||
|
sh: should sh support ; () & --- need malloc
|
||||||
|
sh: stop stdin on ctrl-d (for cat > y)
|
37
cat.c
37
cat.c
|
@ -1,17 +1,32 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include "stat.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
char buf[513];
|
char buf[513];
|
||||||
|
|
||||||
|
void
|
||||||
|
rfile(int fd)
|
||||||
|
{
|
||||||
|
int cc;
|
||||||
|
|
||||||
|
while((cc = read(fd, buf, sizeof(buf) - 1)) > 0){
|
||||||
|
buf[cc] = '\0';
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
|
if(cc < 0){
|
||||||
|
puts("cat: read error\n");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int fd, i, cc;
|
int fd, i;
|
||||||
|
|
||||||
if(argc < 2){
|
|
||||||
puts("Usage: cat files...\n");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
rfile(0);
|
||||||
|
} else {
|
||||||
for(i = 1; i < argc; i++){
|
for(i = 1; i < argc; i++){
|
||||||
fd = open(argv[i], 0);
|
fd = open(argv[i], 0);
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
|
@ -20,16 +35,10 @@ main(int argc, char *argv[])
|
||||||
puts("\n");
|
puts("\n");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
while((cc = read(fd, buf, sizeof(buf) - 1)) > 0){
|
rfile(fd);
|
||||||
buf[cc] = '\0';
|
|
||||||
puts(buf);
|
|
||||||
}
|
|
||||||
if(cc < 0){
|
|
||||||
puts("cat: read error\n");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
17
console.c
17
console.c
|
@ -304,26 +304,31 @@ char kbd_buf[KBD_BUF];
|
||||||
int kbd_r;
|
int kbd_r;
|
||||||
int kbd_w;
|
int kbd_w;
|
||||||
struct spinlock kbd_lock;
|
struct spinlock kbd_lock;
|
||||||
|
static uint shift;
|
||||||
|
|
||||||
void
|
void
|
||||||
kbd_intr()
|
kbd_intr()
|
||||||
{
|
{
|
||||||
uint st, data, c;
|
uint st, data, c;
|
||||||
static uint shift;
|
|
||||||
|
acquire(&kbd_lock);
|
||||||
|
|
||||||
st = inb(KBSTATP);
|
st = inb(KBSTATP);
|
||||||
if ((st & KBS_DIB) == 0){
|
if ((st & KBS_DIB) == 0){
|
||||||
|
release(&kbd_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data = inb(KBDATAP);
|
data = inb(KBDATAP);
|
||||||
|
|
||||||
if (data == 0xE0) {
|
if (data == 0xE0) {
|
||||||
shift |= E0ESC;
|
shift |= E0ESC;
|
||||||
|
release(&kbd_lock);
|
||||||
return;
|
return;
|
||||||
} else if (data & 0x80) {
|
} else if (data & 0x80) {
|
||||||
// Key released
|
// Key released
|
||||||
data = (shift & E0ESC ? data : data & 0x7F);
|
data = (shift & E0ESC ? data : data & 0x7F);
|
||||||
shift &= ~(shiftcode[data] | E0ESC);
|
shift &= ~(shiftcode[data] | E0ESC);
|
||||||
|
release(&kbd_lock);
|
||||||
return;
|
return;
|
||||||
} else if (shift & E0ESC) {
|
} else if (shift & E0ESC) {
|
||||||
// Last character was an E0 escape; or with 0x80
|
// Last character was an E0 escape; or with 0x80
|
||||||
|
@ -341,8 +346,12 @@ kbd_intr()
|
||||||
else if ('A' <= c && c <= 'Z')
|
else if ('A' <= c && c <= 'Z')
|
||||||
c += 'a' - 'A';
|
c += 'a' - 'A';
|
||||||
}
|
}
|
||||||
|
|
||||||
acquire(&kbd_lock);
|
// xxx hack
|
||||||
|
if (c == 0x0) {
|
||||||
|
release(&kbd_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(((kbd_w + 1) % KBD_BUF) != kbd_r){
|
if(((kbd_w + 1) % KBD_BUF) != kbd_r){
|
||||||
kbd_buf[kbd_w++] = c;
|
kbd_buf[kbd_w++] = c;
|
||||||
|
@ -367,7 +376,7 @@ console_read(int minor, char *dst, int n)
|
||||||
sleep(&kbd_r, &kbd_lock);
|
sleep(&kbd_r, &kbd_lock);
|
||||||
|
|
||||||
while(n > 0 && kbd_w != kbd_r){
|
while(n > 0 && kbd_w != kbd_r){
|
||||||
*dst = kbd_buf[kbd_r];
|
*dst = (kbd_buf[kbd_r]) & 0xff;
|
||||||
cons_putc(*dst & 0xff);
|
cons_putc(*dst & 0xff);
|
||||||
dst++;
|
dst++;
|
||||||
--n;
|
--n;
|
||||||
|
|
1
defs.h
1
defs.h
|
@ -16,6 +16,7 @@ struct jmpbuf;
|
||||||
void setupsegs(struct proc *);
|
void setupsegs(struct proc *);
|
||||||
struct proc * copyproc(struct proc*);
|
struct proc * copyproc(struct proc*);
|
||||||
struct spinlock;
|
struct spinlock;
|
||||||
|
int growproc(int);
|
||||||
void sleep(void *, struct spinlock *);
|
void sleep(void *, struct spinlock *);
|
||||||
void wakeup(void *);
|
void wakeup(void *);
|
||||||
void scheduler(void);
|
void scheduler(void);
|
||||||
|
|
2
echo.c
2
echo.c
|
@ -1,3 +1,5 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include "stat.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
2
lapic.c
2
lapic.c
|
@ -120,7 +120,7 @@ lapic_timerinit(void)
|
||||||
void
|
void
|
||||||
lapic_timerintr(void)
|
lapic_timerintr(void)
|
||||||
{
|
{
|
||||||
cprintf("cpu%d: timer interrupt!\n", cpu());
|
// cprintf("cpu%d: timer interrupt!\n", cpu());
|
||||||
lapic_write (LAPIC_EOI, 0);
|
lapic_write (LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
ls.c
57
ls.c
|
@ -7,13 +7,24 @@ char buf[512];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct dirent dirent;
|
struct dirent dirent;
|
||||||
|
|
||||||
|
void
|
||||||
|
pname(char *n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; (i < DIRSIZ) && (n[i] != '\0') ; i++) {
|
||||||
|
printf(1, "%c", n[i]);
|
||||||
|
}
|
||||||
|
for (; i < DIRSIZ; i++)
|
||||||
|
printf(1, " ");
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
uint off;
|
uint off;
|
||||||
uint sz;
|
uint sz;
|
||||||
int i;
|
|
||||||
|
|
||||||
if(argc > 2){
|
if(argc > 2){
|
||||||
puts("Usage: ls [dir]\n");
|
puts("Usage: ls [dir]\n");
|
||||||
|
@ -23,7 +34,7 @@ main(int argc, char *argv[])
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
fd = open(argv[1], 0);
|
fd = open(argv[1], 0);
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
printf(2, "ls: cannot open dir %s\n", argv[1]);
|
printf(2, "ls: cannot open %s\n", argv[1]);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -38,31 +49,31 @@ main(int argc, char *argv[])
|
||||||
printf(2, "ls: cannot stat dir\n");
|
printf(2, "ls: cannot stat dir\n");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
if (st.st_type != T_DIR) {
|
|
||||||
printf(2, "ls: dir is not a directory\n");
|
switch (st.st_type) {
|
||||||
}
|
case T_FILE:
|
||||||
sz = st.st_size;
|
pname(argv[1]);
|
||||||
for(off = 0; off < sz; off += sizeof(struct dirent)) {
|
printf(1, "%d %d %d\n", st.st_type, st.st_ino, st.st_size);
|
||||||
if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
|
break;
|
||||||
printf(1, "ls: read error\n");
|
case T_DIR:
|
||||||
break;
|
sz = st.st_size;
|
||||||
}
|
for(off = 0; off < sz; off += sizeof(struct dirent)) {
|
||||||
if (dirent.inum != 0) {
|
if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
|
||||||
// xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..)
|
printf(1, "ls: read error\n");
|
||||||
if (stat (dirent.name, &st) < 0) {
|
break;
|
||||||
printf(1, "stat: failed %s\n", dirent.name);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < DIRSIZ; i++) {
|
if (dirent.inum != 0) {
|
||||||
if (dirent.name[i] != '\0')
|
// xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..)
|
||||||
printf(1, "%c", dirent.name[i]);
|
if (stat (dirent.name, &st) < 0) {
|
||||||
else
|
printf(1, "stat: failed %s\n", dirent.name);
|
||||||
printf(1, " ");
|
continue;
|
||||||
|
}
|
||||||
|
pname(dirent.name);
|
||||||
|
printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
|
||||||
}
|
}
|
||||||
printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
18
proc.c
18
proc.c
|
@ -138,6 +138,24 @@ copyproc(struct proc* p)
|
||||||
return np;
|
return np;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
growproc(int n)
|
||||||
|
{
|
||||||
|
struct proc *cp = curproc[cpu()];
|
||||||
|
char *newmem, *oldmem;
|
||||||
|
|
||||||
|
newmem = kalloc(cp->sz + n);
|
||||||
|
if(newmem == 0) return -1;
|
||||||
|
memmove(newmem, cp->mem, cp->sz);
|
||||||
|
memset(newmem + cp->sz, 0, n);
|
||||||
|
oldmem = cp->mem;
|
||||||
|
cp->mem = newmem;
|
||||||
|
kfree(oldmem, cp->sz);
|
||||||
|
cp->sz += n;
|
||||||
|
cprintf("growproc: added %d bytes\n", n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Per-CPU process scheduler.
|
// Per-CPU process scheduler.
|
||||||
// Each CPU calls scheduler() after setting itself up.
|
// Each CPU calls scheduler() after setting itself up.
|
||||||
// Scheduler never returns. It loops, doing:
|
// Scheduler never returns. It loops, doing:
|
||||||
|
|
308
sh.c
308
sh.c
|
@ -4,52 +4,296 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
|
|
||||||
char *args[100];
|
#define BUFSIZ 512
|
||||||
void parse(char buf[]);
|
#define MAXARGS 10
|
||||||
|
#define MAXNODE 2
|
||||||
|
|
||||||
|
// only allocate nodes for i/o redir; at some point we may have to build a
|
||||||
|
// a real parse tree.
|
||||||
|
struct node {
|
||||||
|
int token;
|
||||||
|
char *s;
|
||||||
|
};
|
||||||
|
struct node list[MAXNODE];
|
||||||
|
int nextnode;
|
||||||
|
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
char *argv[MAXARGS];
|
||||||
|
char argv0buf[BUFSIZ];
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
int debug = 1;
|
||||||
|
|
||||||
|
int parse(char *s);
|
||||||
|
void runcmd(void);
|
||||||
|
int ioredirection(void);
|
||||||
|
int gettoken(char *s, char **token);
|
||||||
|
int _gettoken(char *s, char **p1, char **p2);
|
||||||
|
void addnode(int token, char *s);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
char buf[128];
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
puts("$ ");
|
puts("$ ");
|
||||||
memset (buf, '\0', sizeof(buf));
|
memset (buf, '\0', sizeof(buf));
|
||||||
gets(buf, sizeof(buf));
|
gets(buf, sizeof(buf));
|
||||||
if(buf[0] == '\0')
|
if (parse(buf) < 0)
|
||||||
continue;
|
continue;
|
||||||
pid = fork();
|
runcmd();
|
||||||
if(pid == 0){
|
|
||||||
parse(buf);
|
|
||||||
if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == '\0') { // cd
|
|
||||||
chdir(&buf[3]);
|
|
||||||
} else {
|
|
||||||
exec(buf, args);
|
|
||||||
printf(1, "%s: not found\n", buf);
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(pid > 0)
|
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
parse(char buf[])
|
parse(char *s)
|
||||||
{
|
{
|
||||||
int j = 1;
|
char *t;
|
||||||
int i;
|
int c;
|
||||||
args[0] = buf;
|
|
||||||
for (i = 0; buf[i] != '\0'; i++) {
|
gettoken(s, 0);
|
||||||
if (buf[i] == ' ') {
|
|
||||||
buf[i] = '\0';
|
argc = 0;
|
||||||
args[j++] = buf + i + 1;
|
nextnode = 0;
|
||||||
if (j >= 100) {
|
while (1) {
|
||||||
printf(2, "too many args\n");
|
switch ((c = gettoken(0, &t))) {
|
||||||
exit();
|
|
||||||
|
case 'w': // Add an argument
|
||||||
|
if (argc == MAXARGS) {
|
||||||
|
printf(2, "too many arguments\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
argv[argc++] = t;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<': // Input redirection
|
||||||
|
// Grab the filename from the argument list
|
||||||
|
if (gettoken(0, &t) != 'w') {
|
||||||
|
printf(2, "syntax error: < not followed by word\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addnode('<', t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '>': // Output redirection
|
||||||
|
// Grab the filename from the argument list
|
||||||
|
if (gettoken(0, &t) != 'w') {
|
||||||
|
printf(2, "syntax error: > not followed by word\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addnode('>', t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0: // String is complete
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf(2, "syntax error: bad return %d from gettoken", c);
|
||||||
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args[j] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
runcmd(void)
|
||||||
|
{
|
||||||
|
int i, r, pid;
|
||||||
|
|
||||||
|
// Return immediately if command line was empty.
|
||||||
|
if(argc == 0) {
|
||||||
|
if (debug)
|
||||||
|
printf(2, "EMPTY COMMAND\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up command line.
|
||||||
|
// Read all commands from the filesystem: add an initial '/' to
|
||||||
|
// the command name.
|
||||||
|
// This essentially acts like 'PATH=/'.
|
||||||
|
if (argv[0][0] != '/') {
|
||||||
|
argv0buf[0] = '/';
|
||||||
|
strcpy(argv0buf + 1, argv[0]);
|
||||||
|
argv[0] = argv0buf;
|
||||||
|
}
|
||||||
|
argv[argc] = 0;
|
||||||
|
|
||||||
|
// Print the command.
|
||||||
|
if (debug) {
|
||||||
|
printf(2, "[%d] SPAWN:", getpid());
|
||||||
|
for (i = 0; argv[i]; i++)
|
||||||
|
printf(2, " %s", argv[i]);
|
||||||
|
for (i = 0; i < nextnode; i++) {
|
||||||
|
printf(2, "%c %s", list[i].token, list[i].s);
|
||||||
|
}
|
||||||
|
printf(2, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[0], "/cd") == 0) {
|
||||||
|
if (debug) printf (2, "/cd %s is build in\n", argv[1]);
|
||||||
|
chdir(argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
if (ioredirection() < 0)
|
||||||
|
exit();
|
||||||
|
if ((r = exec(argv0buf, (char**) argv)) < 0) {
|
||||||
|
printf(2, "exec %s: %d\n", argv[0], r);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid > 0) {
|
||||||
|
if (debug)
|
||||||
|
printf(2, "[%d] WAIT %s\n", getpid(), argv[0]);
|
||||||
|
wait();
|
||||||
|
if (debug)
|
||||||
|
printf(2, "[%d] wait finished\n", getpid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ioredirection(void)
|
||||||
|
{
|
||||||
|
int i, fd, dfd;
|
||||||
|
|
||||||
|
for (i = 0; i < nextnode; i++) {
|
||||||
|
switch (list[i].token) {
|
||||||
|
case '<':
|
||||||
|
if ((fd = open(list[i].s, O_RDONLY)) < 0) {
|
||||||
|
printf(2, "failed to open %s for read: %d", list[i].s, fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
printf(2, "redirect 0 from %s\n", list[i].s);
|
||||||
|
|
||||||
|
close(0);
|
||||||
|
if ((dfd = dup(fd)) < 0)
|
||||||
|
printf(2, "dup failed\n");
|
||||||
|
if (debug)
|
||||||
|
printf(2, "dup returns %d\n", dfd);
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
if ((fd = open(list[i].s, O_WRONLY|O_CREATE)) < 0) {
|
||||||
|
printf(2, "failed to open %s for write: %d", list[i].s, fd);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
printf(2, "redirect 1 to %s\n", list[i].s);
|
||||||
|
|
||||||
|
if (close(1) < 0)
|
||||||
|
printf(2, "close 1 failed\n");
|
||||||
|
if ((dfd = dup(fd)) < 0)
|
||||||
|
printf(2, "dup failed\n");
|
||||||
|
if (debug)
|
||||||
|
printf(2, "dup returns %d\n", dfd);
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
addnode(int token, char *s)
|
||||||
|
{
|
||||||
|
if (nextnode >= MAXNODE) {
|
||||||
|
printf(2, "addnode: ran out of nodes\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list[nextnode].token = token;
|
||||||
|
list[nextnode].s = s;
|
||||||
|
nextnode++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// gettoken(s, 0) prepares gettoken for subsequent calls and returns 0.
|
||||||
|
// gettoken(0, token) parses a shell token from the previously set string,
|
||||||
|
// null-terminates that token, stores the token pointer in '*token',
|
||||||
|
// and returns a token ID (0, '<', '>', '|', or 'w').
|
||||||
|
// Subsequent calls to 'gettoken(0, token)' will return subsequent
|
||||||
|
// tokens from the string.
|
||||||
|
|
||||||
|
int
|
||||||
|
gettoken(char *s, char **p1)
|
||||||
|
{
|
||||||
|
static int c, nc;
|
||||||
|
static char* np1, *np2;
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
nc = _gettoken(s, &np1, &np2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
c = nc;
|
||||||
|
*p1 = np1;
|
||||||
|
nc = _gettoken(np2, &np1, &np2);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get the next token from string s.
|
||||||
|
// Set *p1 to the beginning of the token and *p2 just past the token.
|
||||||
|
// Returns
|
||||||
|
// 0 for end-of-string;
|
||||||
|
// < for <;
|
||||||
|
// > for >;
|
||||||
|
// | for |;
|
||||||
|
// w for a word.
|
||||||
|
//
|
||||||
|
// Eventually (once we parse the space where the \0 will go),
|
||||||
|
// words get nul-terminated.
|
||||||
|
#define WHITESPACE " \t\r\n"
|
||||||
|
#define SYMBOLS "<|>&;()"
|
||||||
|
|
||||||
|
int
|
||||||
|
_gettoken(char *s, char **p1, char **p2)
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
|
||||||
|
if (s == 0) {
|
||||||
|
if (debug > 1)
|
||||||
|
printf(2, "GETTOKEN NULL\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug > 1)
|
||||||
|
printf(2, "GETTOKEN: %s\n", s);
|
||||||
|
|
||||||
|
*p1 = 0;
|
||||||
|
*p2 = 0;
|
||||||
|
|
||||||
|
while (strchr(WHITESPACE, *s))
|
||||||
|
*s++ = 0;
|
||||||
|
if (*s == 0) {
|
||||||
|
if (debug > 1)
|
||||||
|
printf(2, "EOL\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strchr(SYMBOLS, *s)) {
|
||||||
|
t = *s;
|
||||||
|
*p1 = s;
|
||||||
|
*s++ = 0;
|
||||||
|
*p2 = s;
|
||||||
|
if (debug > 1)
|
||||||
|
printf(2, "TOK %c\n", t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
*p1 = s;
|
||||||
|
while (*s && !strchr(WHITESPACE SYMBOLS, *s))
|
||||||
|
s++;
|
||||||
|
*p2 = s;
|
||||||
|
if (debug > 1) {
|
||||||
|
t = **p2;
|
||||||
|
**p2 = 0;
|
||||||
|
printf(2, "WORD: %s\n", *p1);
|
||||||
|
**p2 = t;
|
||||||
|
}
|
||||||
|
return 'w';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
29
syscall.c
29
syscall.c
|
@ -140,6 +140,7 @@ sys_write(void)
|
||||||
return -1;
|
return -1;
|
||||||
if(addr + n > p->sz)
|
if(addr + n > p->sz)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ret = fd_write(p->fds[fd], p->mem + addr, n);
|
ret = fd_write(p->fds[fd], p->mem + addr, n);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -421,6 +422,7 @@ sys_dup(void)
|
||||||
fd_close(fd1);
|
fd_close(fd1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
cp->fds[ufd1] = fd1;
|
||||||
fd1->type = cp->fds[fd]->type;
|
fd1->type = cp->fds[fd]->type;
|
||||||
fd1->readable = cp->fds[fd]->readable;
|
fd1->readable = cp->fds[fd]->readable;
|
||||||
fd1->writeable = cp->fds[fd]->writeable;
|
fd1->writeable = cp->fds[fd]->writeable;
|
||||||
|
@ -449,6 +451,27 @@ sys_link(void)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sys_getpid(void)
|
||||||
|
{
|
||||||
|
struct proc *cp = curproc[cpu()];
|
||||||
|
return cp->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sys_sbrk(void)
|
||||||
|
{
|
||||||
|
int r, n;
|
||||||
|
struct proc *cp = curproc[cpu()];
|
||||||
|
|
||||||
|
if(fetcharg(0, &n) < 0)
|
||||||
|
return -1;
|
||||||
|
r = growproc(n);
|
||||||
|
setupsegs(cp);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_exec(void)
|
sys_exec(void)
|
||||||
{
|
{
|
||||||
|
@ -638,6 +661,12 @@ syscall(void)
|
||||||
case SYS_dup:
|
case SYS_dup:
|
||||||
ret = sys_dup();
|
ret = sys_dup();
|
||||||
break;
|
break;
|
||||||
|
case SYS_getpid:
|
||||||
|
ret = sys_getpid();
|
||||||
|
break;
|
||||||
|
case SYS_sbrk:
|
||||||
|
ret = sys_sbrk();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -15,4 +15,6 @@
|
||||||
#define SYS_mkdir 16
|
#define SYS_mkdir 16
|
||||||
#define SYS_chdir 17
|
#define SYS_chdir 17
|
||||||
#define SYS_dup 18
|
#define SYS_dup 18
|
||||||
|
#define SYS_getpid 19
|
||||||
|
#define SYS_sbrk 20
|
||||||
|
|
||||||
|
|
17
ulib.c
17
ulib.c
|
@ -20,6 +20,14 @@ strcpy(char *s, char *t)
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
strcmp(const char *p, const char *q)
|
||||||
|
{
|
||||||
|
while (*p && *p == *q)
|
||||||
|
p++, q++;
|
||||||
|
return (int) ((unsigned char) *p - (unsigned char) *q);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
strlen(char *s)
|
strlen(char *s)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +48,15 @@ memset(void *dst, int c, unsigned int n)
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
strchr(const char *s, char c)
|
||||||
|
{
|
||||||
|
for (; *s; s++)
|
||||||
|
if (*s == c)
|
||||||
|
return (char *) s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
gets(char *buf, int max)
|
gets(char *buf, int max)
|
||||||
{
|
{
|
||||||
|
|
3
user.h
3
user.h
|
@ -18,10 +18,13 @@ int link(char *, char *);
|
||||||
int mkdir(char *);
|
int mkdir(char *);
|
||||||
int chdir(char *);
|
int chdir(char *);
|
||||||
int dup(int);
|
int dup(int);
|
||||||
|
int getpid();
|
||||||
|
|
||||||
int stat(char *, struct stat *stat);
|
int stat(char *, struct stat *stat);
|
||||||
int puts(char*);
|
int puts(char*);
|
||||||
char* strcpy(char*, char*);
|
char* strcpy(char*, char*);
|
||||||
|
char *strchr(const char *s, char c);
|
||||||
|
int strcmp(const char *p, const char *q);
|
||||||
void printf(int fd, char *fmt, ...);
|
void printf(int fd, char *fmt, ...);
|
||||||
char *gets(char *, int max);
|
char *gets(char *, int max);
|
||||||
unsigned int strlen(char *);
|
unsigned int strlen(char *);
|
||||||
|
|
4
userfs.c
4
userfs.c
|
@ -20,6 +20,10 @@ main(void)
|
||||||
|
|
||||||
printf(stdout, "userfs is running\n");
|
printf(stdout, "userfs is running\n");
|
||||||
|
|
||||||
|
if (sbrk(4096) < 0) {
|
||||||
|
printf(stdout, "sbrk failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
fd = open("echo", 0);
|
fd = open("echo", 0);
|
||||||
if(fd >= 0){
|
if(fd >= 0){
|
||||||
printf(stdout, "open echo ok\n");
|
printf(stdout, "open echo ok\n");
|
||||||
|
|
2
usys.S
2
usys.S
|
@ -25,3 +25,5 @@ STUB(link)
|
||||||
STUB(mkdir)
|
STUB(mkdir)
|
||||||
STUB(chdir)
|
STUB(chdir)
|
||||||
STUB(dup)
|
STUB(dup)
|
||||||
|
STUB(getpid)
|
||||||
|
STUB(sbrk)
|
||||||
|
|
Loading…
Reference in a new issue