Move stdin/stdout/stderr to #cons
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 5 Oct 2016 19:47:24 +0000 (15:47 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 6 Oct 2016 19:41:48 +0000 (15:41 -0400)
It's the same logic, just accessible via 9ns instead of VFS.  #cons/null
already existed.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/cons.c
kern/src/devfs.c
kern/src/process.c

index 2578b49..c782352 100644 (file)
@@ -605,6 +605,9 @@ enum {
        Qpid,
        Qppid,
        Qreboot,
+       Qstdin,
+       Qstdout,
+       Qstderr,
        Qswap,
        Qsysctl,
        Qsysname,
@@ -641,6 +644,9 @@ static struct dirtab consdir[] = {
        {"pid", {Qpid}, NUMSIZE, 0444},
        {"ppid", {Qppid}, NUMSIZE, 0444},
        {"reboot", {Qreboot}, 0, 0660},
+       {"stdin", {Qstdin}, 0, 0666},
+       {"stdout", {Qstdout}, 0, 0666},
+       {"stderr", {Qstderr}, 0, 0666},
        {"swap", {Qswap}, 0, 0664},
        {"sysctl", {Qsysctl}, 0, 0666},
        {"sysname", {Qsysname}, 0, 0664},
@@ -962,6 +968,8 @@ static long consread(struct chan *c, void *buf, long n, int64_t off)
                        return consreadstr((uint32_t) offset, buf, n, tmp);
 #endif
 
+               case Qstdin:
+                       return qread(cons_q, buf, n);
                case Qsysname:
                        /* TODO: this is racy */
                        if (sysname == NULL)
@@ -1182,6 +1190,22 @@ static long conswrite(struct chan *c, void *va, long n, int64_t off)
                        break;
 #endif
 
+               case Qstdout:
+               case Qstderr:
+                       px_lock();
+                       if (waserror()) {
+                               px_unlock();
+                               nexterror();
+                       }
+                       /* TODO: tty hack.  they are sending us an escape sequence, and the
+                        * keyboard would try to print it (which it can't do yet).  The hack
+                        * is even dirtier in that we only detect it if it is the first
+                        * char, and we ignore everything else.  \033 is 0x1b. */
+                       if (((char*)va)[0] != '\033')
+                               cputbuf(va, n);
+                       poperror();
+                       px_unlock();
+                       return n;
                case Qsysname:
                        /* TODO: this is racy */
                        if (offset != 0)
@@ -1202,6 +1226,18 @@ static long conswrite(struct chan *c, void *va, long n, int64_t off)
        return n;
 }
 
+static char *cons_chaninfo(struct chan *ch, char *ret, size_t ret_l)
+{
+       switch ((uint32_t)ch->qid.path) {
+       case Qstdin:
+               snprintf(ret, ret_l, "qio len: %d", qlen(cons_q));
+               break;
+       default:
+               return devchaninfo(ch, ret, ret_l);
+       }
+       return ret;
+}
+
 struct dev consdevtab __devtab = {
        .name = "cons",
 
@@ -1221,7 +1257,7 @@ struct dev consdevtab __devtab = {
        .remove = devremove,
        .wstat = devwstat,
        .power = devpower,
-       .chaninfo = devchaninfo,
+       .chaninfo = cons_chaninfo,
 };
 
 static char *devname(void)
index e6edaee..e6926e3 100644 (file)
 #include <kmalloc.h>
 #include <ns.h>
 
-/* These structs are declared again and initialized farther down */
-struct file_operations dev_f_op_stdin;
-struct file_operations dev_f_op_stdout;
-struct file_operations dev_f_op_null;
-
-struct file *dev_stdin, *dev_stdout, *dev_stderr, *dev_null;
-
 void devfs_init(void)
 {
        int mode;
@@ -33,16 +26,6 @@ void devfs_init(void)
        } else {
                kref_put(&dentry->d_kref);
        }
-       /* Notice we don't kref_put().  We're storing the refs globally */
-       dev_stdin = make_device("/dev/stdin", S_IRUSR | S_IRGRP | S_IROTH,
-                               __S_IFCHR, &dev_f_op_stdin);
-       dev_stdout = make_device("/dev/stdout", S_IWUSR | S_IWGRP | S_IWOTH,
-                                __S_IFCHR, &dev_f_op_stdout);
-       /* Note stderr uses the same f_op as stdout */
-       dev_stderr = make_device("/dev/stderr", S_IWUSR | S_IWGRP | S_IWOTH,
-                                __S_IFCHR, &dev_f_op_stdout);
-       dev_null = make_device("/dev/null", S_IWUSR | S_IWGRP | S_IWOTH,
-                              __S_IFCHR, &dev_f_op_null);
 }
 
 /* Creates a device node at a given location in the FS-tree */
@@ -74,106 +57,3 @@ int dev_mmap(struct file *file, struct vm_region *vmr)
        set_errno(EINVAL);
        return -1;
 }
-
-/* this is really /dev/console, and will need some tty work.  for now, no matter
- * how much they ask for, we return one character at a time. */
-ssize_t dev_stdin_read(struct file *file, char *buf, size_t count,
-                       off64_t *offset)
-{
-       char c;
-       extern struct queue *cons_q;
-
-       if (!count)
-               return 0;
-       return qread(cons_q, buf, count);
-}
-
-ssize_t dev_stdout_write(struct file *file, const char *buf, size_t count,
-                         off64_t *offset)
-{
-       char *t_buf;
-       struct proc *p = current;
-       if (p)
-               t_buf = user_memdup_errno(p, buf, count);
-       else
-               t_buf = (char*)buf;
-       if (!t_buf)
-               return -1;
-       /* TODO: tty hack.  they are sending us an escape sequence, and the keyboard
-        * would try to print it (which it can't do yet).  The hack is even dirtier
-        * in that we only detect it if it is the first char, and we ignore
-        * everything else.  \033 is 0x1b. */
-       if (t_buf[0] != '\033') {
-               px_lock();
-               cputbuf(t_buf, count);
-               px_unlock();
-       }
-       if (p)
-               user_memdup_free(p, t_buf);
-       return count;
-}
-
-/* stdin/stdout/stderr file ops */
-struct file_operations dev_f_op_stdin = {
-       dev_c_llseek,
-       dev_stdin_read,
-       0,      /* write - can't write to stdin */
-       kfs_readdir,    /* this will fail gracefully */
-       dev_mmap,
-       kfs_open,
-       kfs_flush,
-       kfs_release,
-       0,      /* fsync - makes no sense */
-       kfs_poll,
-       0,      /* readv */
-       0,      /* writev */
-       kfs_sendpage,
-       kfs_check_flags,
-};
-
-struct file_operations dev_f_op_stdout = {
-       dev_c_llseek,
-       0,      /* read - can't read stdout */
-       dev_stdout_write,
-       kfs_readdir,    /* this will fail gracefully */
-       dev_mmap,
-       kfs_open,
-       kfs_flush,
-       kfs_release,
-       0,      /* fsync - makes no sense */
-       kfs_poll,
-       0,      /* readv */
-       0,      /* writev */
-       kfs_sendpage,
-       kfs_check_flags,
-};
-
-ssize_t dev_null_read(struct file *file, char *buf, size_t count,
-                      off64_t *offset)
-{
-       return 0;
-}
-
-/* /dev/null: just take whatever was given and pretend it was written */
-ssize_t dev_null_write(struct file *file, const char *buf, size_t count,
-                       off64_t *offset)
-{
-       return count;
-}
-
-struct file_operations dev_f_op_null = {
-       dev_c_llseek,
-       dev_null_read,
-       dev_null_write,
-       kfs_readdir,    /* this will fail gracefully */
-       dev_mmap,
-       kfs_open,
-       kfs_flush,
-       kfs_release,
-       0,      /* fsync - makes no sense */
-       kfs_poll,
-       0,      /* readv */
-       0,      /* writev */
-       kfs_sendpage,
-       kfs_check_flags,
-};
index c020f6e..c5c0c5c 100644 (file)
@@ -23,7 +23,6 @@
 #include <monitor.h>
 #include <elf.h>
 #include <arsc_server.h>
-#include <devfs.h>
 #include <kmalloc.h>
 #include <ros/procinfo.h>
 
@@ -305,6 +304,26 @@ void proc_init_procdata(struct proc *p)
        atomic_set(&p->procdata->vcore_preempt_data[0].flags, VC_SCP_NOVCCTX);
 }
 
+static void proc_open_stdfds(struct proc *p)
+{
+       int fd;
+       struct proc *old_current = current;
+
+       /* Due to the way the syscall helpers assume the target process is current,
+        * we need to set current temporarily.  We don't use switch_to, since that
+        * actually loads the process's address space, which might be empty or
+        * incomplete.  These syscalls shouldn't access user memory, especially
+        * considering how we're probably in the boot pgdir. */
+       current = p;
+       fd = sysopenat(AT_FDCWD, "#cons/stdin", O_READ);
+       assert(fd == 0);
+       fd = sysopenat(AT_FDCWD, "#cons/stdout", O_WRITE);
+       assert(fd == 1);
+       fd = sysopenat(AT_FDCWD, "#cons/stderr", O_WRITE);
+       assert(fd == 2);
+       current = old_current;
+}
+
 /* Allocates and initializes a process, with the given parent.  Currently
  * writes the *p into **pp, and returns 0 on success, < 0 for an error.
  * Errors include:
@@ -396,13 +415,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent, int flags)
                        clone_fdt(&parent->open_files, &p->open_files);
        } else {
                /* no parent, we're created from the kernel */
-               int fd;
-               fd = insert_file(&p->open_files, dev_stdin,  0, TRUE, FALSE);
-               assert(fd == 0);
-               fd = insert_file(&p->open_files, dev_stdout, 1, TRUE, FALSE);
-               assert(fd == 1);
-               fd = insert_file(&p->open_files, dev_stderr, 2, TRUE, FALSE);
-               assert(fd == 2);
+               proc_open_stdfds(p);
        }
        /* Init the ucq hash lock */
        p->ucq_hashlock = (struct hashlock*)&p->ucq_hl_noref;