summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/fd.c124
-rw-r--r--fs/fd.h4
-rw-r--r--kernel/syscalls.c85
-rw-r--r--userspace/cat.c57
-rw-r--r--userspace/grep.c20
-rw-r--r--userspace/newcalls.h5
-rw-r--r--userspace/piper.c31
7 files changed, 218 insertions, 108 deletions
diff --git a/fs/fd.c b/fs/fd.c
index f8981a5..1215679 100644
--- a/fs/fd.c
+++ b/fs/fd.c
@@ -33,6 +33,20 @@ bool fd_close(fd* f)
return f->close(f->data);
}
+fd fd_dupl(fd* f)
+{
+ return f->dupl(f);
+}
+
+static fd default_dupl(fd *f)
+{
+ return *f;
+}
+void default_close(void* x)
+{
+ // nothin
+}
+
//----
void* ext2_init(char *path)
{
@@ -109,11 +123,44 @@ void sysfs_close(uint32_t *data)
kbfree(data); // free memory holding ringbuffer information
}
-void pipe_close(uint32_t *data)
+void pipe_r_close(uint8_t *data)
{
- ringbuffer *r=data;
- ringbuffer_free(data); // free ringbuffer buffer
- kbfree(data); // free memory holding ringbuffer information
+ uint8_t *mem=data+sizeof(ringbuffer);
+ *mem-=1;
+ klog("closing read end of pipe, ref count=%d",*mem);
+ /*
+ if(*mem==0) // TODO : check other end too! and close on w_close
+ {
+ ringbuffer *r=data;
+ ringbuffer_free(data); // free ringbuffer buffer
+ kbfree(data); // free memory holding ringbuffer information
+ }
+ */
+}
+
+void pipe_w_close(uint8_t *data)
+{
+ uint8_t *mem=data+sizeof(ringbuffer);
+ mem+=4;
+ *mem-=1;
+ klog("closing write end of pipe, ref count=%d",*mem);
+}
+
+static fd pipe_r_dupl(fd *f)
+{
+ uint8_t *mem=f->data+sizeof(ringbuffer);
+ *mem+=1;
+ klog("duplicating read end of pipe, ref count=%d",*mem);
+ return *f;
+}
+
+static fd pipe_w_dupl(fd *f)
+{
+ uint8_t *mem=f->data+sizeof(ringbuffer);
+ mem+=4;
+ *mem+=1;
+ klog("duplicating write end of pipe, ref count=%d",*mem);
+ return *f;
}
void get_sysfs_data(ringbuffer *r,char *format_string, ...)
@@ -135,19 +182,6 @@ bool fifo_eof(uint32_t* data)
return false;
}
-// TODO remove and use fd_from_ringbuffer?
-fd fd_from_fifo(fifo* fif)
-{
- fd f;
- f.type=FD_TYPE_FIFO_BUFFERED;
- f.data=fif;
- f.read=fifo_get;
- f.write=fifo_put;
- f.eof=fifo_eof;
-// f.close=fd_close; //TODO.. etc also otehr and cleanups
- f.has=fifo_has;
- return f;
-}
uint8_t pipe_get(uint32_t *data)
{
@@ -164,11 +198,19 @@ bool pipe_has(uint32_t *data)
return ringbuffer_has(data);
}
-bool pipe_eof(uint32_t *data)
+bool pipe_eof(uint8_t *data)
{
- return 0;
+
+ uint8_t *mem=data+sizeof(ringbuffer);
+ mem+=4;
+
+ //we assume EOF if there is no data anymore AND no writers!
+ return (!ringbuffer_has(data))&&(*mem==0);
}
+
+/////
+
int fds_from_pipe(fd pipefds[2])
{
fd read;
@@ -177,24 +219,36 @@ int fds_from_pipe(fd pipefds[2])
read.type=FD_TYPE_PIPE;
wrt.type=FD_TYPE_PIPE;
- read.data=kballoc(1);
- wrt.data=read.data;
+ uint8_t *mem=kballoc(1);
+
+ read.data=mem;
+ wrt.data=mem;
ringbuffer r=ringbuffer_init(1);
- memcpy(read.data,&r,sizeof(ringbuffer));
+ memcpy(mem,&r,sizeof(ringbuffer));
+ mem+=sizeof(ringbuffer);
+ *mem=1;
+ mem+=4;
+ *mem=1;
read.read=pipe_get;
+ wrt.read=0;
+
wrt.write=pipe_put;
+ read.write=0;
read.has=pipe_has;
- wrt.has=pipe_has;
+ wrt.has=0;
read.eof=pipe_eof;
- wrt.eof=pipe_eof;
+ wrt.eof=0;
+
+ read.close=pipe_r_close;
+ wrt.close=pipe_w_close;
- read.close=0;
- wrt.close=0;
+ read.dupl=pipe_r_dupl;
+ wrt.dupl=pipe_w_dupl;
pipefds[0]=read;
pipefds[1]=wrt;
@@ -212,6 +266,7 @@ fd fd_from_path(char* path)
f.close=ext2_close;
f.eof=ext2_eof;
f.has=ext2_has;
+ f.dupl=default_dupl;
return f;
}
@@ -237,6 +292,21 @@ fd fd_from_sysfs(void(*g)(ringbuffer *r,void (*f)(ringbuffer *r,char *fmt, ...))
f.close=sysfs_close;
f.has=sysfs_has;
f.eof=sysfs_eof;
-
+ f.dupl=default_dupl;
+ f.close=default_close;
+ return f;
+}
+
+fd fd_from_fifo(fifo* fif)
+{
+ fd f;
+ f.type=FD_TYPE_FIFO;
+ f.data=fif;
+ f.read=fifo_get;
+ f.write=fifo_put;
+ f.eof=fifo_eof;
+ f.has=fifo_has;
+ f.dupl=default_dupl;
+ f.close=default_close;
return f;
}
diff --git a/fs/fd.h b/fs/fd.h
index 64a53ed..21037c8 100644
--- a/fs/fd.h
+++ b/fs/fd.h
@@ -10,7 +10,7 @@
#include "ringbuffer.h"
enum FD_TYPE{
- FD_TYPE_FIFO_BUFFERED=1,
+ FD_TYPE_FIFO=1,
FD_TYPE_EXT2_FILE=2,
FD_TYPE_EXT2_DIR=3,
FD_TYPE_SYSFS=4,
@@ -24,6 +24,7 @@ typedef struct fd_struct
bool (*has)(struct fd_struct*);
bool (*eof)(struct fd_struct*);
bool (*close)(struct fd_struct*);
+ struct fd_struct (*dupl)(struct fd_struct *);
uint8_t type;
void *data; // opaque data
@@ -34,6 +35,7 @@ bool fd_has(fd*);
bool fd_eof(fd*);
bool fd_write(fd*,uint8_t);
bool fd_close(fd*);
+fd fd_dupl(fd*);
fd fd_from_fifo(fifo* f);
fd fd_from_path(char *path);
diff --git a/kernel/syscalls.c b/kernel/syscalls.c
index dfcdaae..ee100e2 100644
--- a/kernel/syscalls.c
+++ b/kernel/syscalls.c
@@ -28,22 +28,28 @@
//TODO move to process.c and implement per process //
static fd fds[MAX_PID][MAX_FD];
-static uint32_t next_fd[MAX_PID];
+static bool open_fd[MAX_PID][MAX_FD];
void fd_init_std_streams(uint32_t pid)
{
if(pid==0)
{
//stdin / stdout /stderr
- fds[0][next_fd[0]++]=fd_from_ringbuffer();
- fds[0][next_fd[0]++]=fd_from_fb_term();
- fds[0][next_fd[0]++]=fd_from_fb_term();
+ fds[0][0]=fd_from_ringbuffer();
+ fds[0][1]=fd_from_fb_term();
+ fds[0][2]=fd_from_fb_term();
+ open_fd[0][0]=true;
+ open_fd[0][1]=true;
+ open_fd[0][2]=true;
}
else
{
fds[pid][0]=fds[0][0];
fds[pid][1]=fds[0][1];
fds[pid][2]=fds[0][2];
+ open_fd[pid][0]=true;
+ open_fd[pid][1]=true;
+ open_fd[pid][2]=true;
}
}
@@ -248,22 +254,38 @@ int syscall_execve(const char *name, char *const argv[], char *const env[], int
return 0;
}
+/** helper */
+int nextfd(int pid)
+{
+ for(int i=0;i<MAX_FD;i++)
+ if(!open_fd[pid][i])
+ {
+ open_fd[pid][i]=true;
+ return i;
+ }
+
+ return -1;
+}
int syscall_open(char *name, int flags, int mode,uint32_t pid)
{
- fds[pid][next_fd[pid]]=mount_file_open(name);
- if(*(uint32_t *)fds[pid][next_fd[pid]].data==0)return -1;
-
- next_fd[pid]++;
- return next_fd[pid]-1;
+ uint32_t fdn=nextfd(pid);
+ fds[pid][fdn]=mount_file_open(name);
+ if(*(uint32_t *)fds[pid][fdn].data==0)return -1;
+ return fdn;
}
// pid_t fork(void);
uint32_t syscall_fork(int none1, int none2, int none3, int pid)
{
uint32_t newpid=task_fork(pid);
- fds[newpid][0]=fds[pid][0];
- fds[newpid][1]=fds[pid][1];
- fds[newpid][2]=fds[pid][2];
+
+ for(int i=0;i<MAX_FD;i++)
+ {
+ if(!open_fd[pid][i])continue;
+ fds[newpid][i]=fd_dupl(&fds[pid][i]);
+ open_fd[newpid][i]=true;
+ }
+
return newpid;
}
@@ -282,6 +304,15 @@ uint32_t syscall_exit(int status, uint32_t none1, uint32_t none2,int pid)
{
fixme("free allll mem");
klog("pid %d exited with %d",pid,status);
+ for(int i=0;i<MAX_FD;i++)
+ {
+ if(open_fd[pid][i])
+ {
+ fd_close(&fds[pid][i]);
+ open_fd[pid][i]=false;
+ }
+
+ }
task_exit(pid);
return 0;
}
@@ -289,15 +320,20 @@ uint32_t syscall_exit(int status, uint32_t none1, uint32_t none2,int pid)
// int close (int fd) (TODO; close or not to close open filedescirptors?)
int syscall_close(int file,int none1,int none2,int pid)
{
- if(file<3)return 0;
- fd_close(&fds[pid][file]);
+ if(open_fd[pid][file])
+ {
+ fd_close(&fds[pid][file]);
+ open_fd[pid][file]=false;
+ }
+
return 0;
}
// TODO: check if file is a termminal!
int syscall_isatty(int file,int none1,int none2,int pid)
{
- return 1;
+ if(fds[pid][file].type==FD_TYPE_FIFO)return 1;
+ return 0;
}
// TODO: per process basis!
@@ -324,22 +360,23 @@ uint32_t syscall_pipe(uint32_t *addr,int none1, int none2, uint32_t pid)
fd pipfds[2];
int ret=fds_from_pipe(pipfds);
- fds[pid][next_fd[pid]]=pipfds[0] ;
- *addr=next_fd[pid];
- addr++;
+ int fd1=nextfd(pid);
+ int fd2=nextfd(pid);
- next_fd[pid]++;
+ fds[pid][fd1]=pipfds[0] ;
+ *addr=fd1;
+ addr++;
- fds[pid][next_fd[pid]]=pipfds[1] ;
- *addr=next_fd[pid];
- next_fd[pid]++;
+ fds[pid][fd2]=pipfds[1] ;
+ *addr=fd2;
return ret;
}
uint32_t syscall_dup2(uint32_t oldfd,int newfd, int none2, uint32_t pid)
{
- fds[pid][newfd]=fds[pid][oldfd];
+ fd_close(&fds[pid][newfd]);
+ fds[pid][newfd]=fd_dupl(&fds[pid][oldfd]);
return newfd;
}
@@ -350,7 +387,7 @@ uint32_t syscall_generic_test(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3,
case SYSCALL_WAIT :
return !task_runs(p1);
case SYSCALL_READ :
- return fd_has(&fds[pid][p1]);
+ return fd_has(&fds[pid][p1])||fd_eof(&fds[pid][p1]);
}
return 1;//other syscalls never block for now.
diff --git a/userspace/cat.c b/userspace/cat.c
index 94cbdaa..41768ea 100644
--- a/userspace/cat.c
+++ b/userspace/cat.c
@@ -3,34 +3,39 @@
int main(int argc, char **argv)
{
- printf("hmm\n");
- printf("pwd=%s\n",getenv("PWD"));
- FILE *f;
- if(argc>1){
- char buf[256];
- if(argv[1][0]!='/')
- {
- sprintf(buf,"%s/%s",getenv("PWD"),argv[1]);
- printf("cat %s\n",buf);
- f=fopen(buf,"r");
- }
- else
- {
- printf("cat %s\n",argv[1]);
- f=fopen(argv[1],"r");
- }
- }
- else f=stdin;
+ // Input (default stdin)
+ FILE *in=stdin;
+
+ // Output
+ FILE *out=stdout;
- setvbuf(stdin,NULL,_IONBF,0);
- setvbuf(stdout,NULL,_IONBF,0);
+ // In case a Filename was supplied
+ if(argc>1){
+ char buf[256];
- char c;
+ // Relative Path
+ if(argv[1][0]!='/')
+ {
+ sprintf(buf,"%s/%s",getenv("PWD"),argv[1]);
+ in=fopen(buf,"r");
+ }
- while(fread(&c,1,1,f))
- {
- printf("%c",c);
- }
+ // Absolute Path
+ else
+ {
+ in=fopen(argv[1],"r");
+ }
+ }
+
+ char buf[256];
+
+ while(1)
+ {
+ int l=fread(buf,1,255,in);
+ buf[l]=0;
+ if(l==0)break;
+ fwrite(buf,1,l,out);
+ }
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/userspace/grep.c b/userspace/grep.c
index c37392f..68d5b7a 100644
--- a/userspace/grep.c
+++ b/userspace/grep.c
@@ -3,15 +3,17 @@
int main(int argc, char **argv)
{
- while(1)
- {
- char buf[256];
- int l=fread(buf,1,255,stdin);
- if(l==0)break;
- buf[l]=0;
- printf("grep: %s",buf);
+ FILE *in=stdin;
+ FILE *out=stdout;
- }
+ while(1)
+ {
+ char buf[2];
+ int l=fread(buf,1,1,in);
+ if(l==0)break;
+ buf[l]=0;
+ fwrite(buf,1,l,out);
+ }
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
diff --git a/userspace/newcalls.h b/userspace/newcalls.h
index 9bc55a5..4568711 100644
--- a/userspace/newcalls.h
+++ b/userspace/newcalls.h
@@ -3,6 +3,7 @@
// this syscall will be moved to newlib later!
#define SYSCALL_CLONE 83
#define SYSCALL_PIPE 84
+#define SYSCALL_DUP2 86
int _clone(void)
{
@@ -12,4 +13,8 @@ int _pipe(uint32_t fds[2])
{
return syscall(SYSCALL_PIPE,fds,0,0);
}
+int _dup2(uint32_t oldfd,uint32_t newfd)
+{
+ return syscall(SYSCALL_DUP2,oldfd,newfd,0);
+}
//
diff --git a/userspace/piper.c b/userspace/piper.c
index f45248e..80cbd27 100644
--- a/userspace/piper.c
+++ b/userspace/piper.c
@@ -1,38 +1,27 @@
#include <stdio.h>
#include "newcalls.h"
+extern **environ;
+
int main()
{
int fds[2];
_pipe(fds);
- printf("opened pipe / in fd=%d,out fd=%d\n",fds[0],fds[1]);
-
int pid=_fork();
if(pid)
{
- while(1) // read forever from our pipe and echo to stdout
- {
- char buf[256];
- int len=fread(buf,1,255,fds[0]);
- //int len=_read(fds[0],buf,255);
- buf[len]=0;
- printf("-\n");
- printf("%s\n",buf);
- printf("-\n");
- }
-
+ _close(fds[1]);
+ _dup2(fds[0],0); // replace stdin with the read-end of pipe
+ char *args[]={"grep",NULL};
+ _execve("/bin/grep",args,environ);
}
else
{
-
- // write to our pipe
- _write(fds[1],"Hello\n",fds[1]);
- _write(fds[1],"Bello\n",fds[1]);
-
- // hang forever
- while(1);
+ _close(fds[0]);
+ _dup2(fds[1],1); // replace stdout with the write-end of our pipe
+ char *args[]={"cat","hello.txt",0};
+ _execve("/bin/cat",args,environ);
}
-
}