tty: Implement /dev/tty and fix some open() bugs
authorAlan Cox <alan@linux.intel.com>
Fri, 22 May 2015 10:35:54 +0000 (11:35 +0100)
committerAlan Cox <alan@linux.intel.com>
Fri, 22 May 2015 10:35:54 +0000 (11:35 +0100)
Some rough edges to fix
Fix various existing crashes on open() - explains the df bug I think
Return correct error codes from device open fails

Kernel/include/kernel.h
Kernel/include/tty.h
Kernel/syscall_fs2.c
Kernel/tty.c

index e01a4a0..133cf15 100644 (file)
@@ -410,6 +410,7 @@ typedef struct u_data {
     inoptr      u_cwd;          /* Index into inode table of cwd. */
     inoptr     u_root;         /* Index into inode table of / */
     inoptr     u_rename;       /* Used in n_open for rename() checking */
+    inoptr     u_ctty;         /* Controlling tty */
 } u_data;
 
 
@@ -704,6 +705,7 @@ extern void readi(inoptr ino, uint8_t flag);
 extern void writei(inoptr ino, uint8_t flag);
 extern int16_t doclose (uint8_t uindex);
 extern inoptr rwsetup (bool is_read, uint8_t *flag);
+extern int dev_openi(inoptr *ino, uint8_t flag);
 
 /* mm.c */
 extern unsigned int uputsys(unsigned char *from, usize_t size);
index 4702018..2218fe8 100644 (file)
@@ -172,9 +172,11 @@ extern int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
 extern int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
 extern int tty_open(uint8_t minor, uint16_t flag);
 extern int tty_close(uint8_t minor);
-extern void tty_exit(void);
 extern int tty_ioctl(uint8_t minor, uarg_t request, char *data);
 
+extern void tty_exit(void);
+extern void tty_post(inoptr ino, uint8_t minor, uint8_t flag);
+
 extern void tty_hangup(uint8_t minor);
 extern void tty_carrier_drop(uint8_t minor);
 extern void tty_carrier_raise(uint8_t minor);
index 0b16935..c7d154b 100644 (file)
@@ -483,33 +483,40 @@ arg_t _open(void)
                        goto cantopen;
                }
        }
+       /* Book our slot in case we block opening a device */
        of_tab[oftindex].o_inode = ino;
 
        perm = getperm(ino);
        if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) {
                udata.u_error = EPERM;
-               goto idrop;
+               goto cantopen;
        }
        if (w) {
                if (getmode(ino) == F_DIR ) {
                        udata.u_error = EISDIR;
-                       goto idrop;
+                       goto cantopen;
                }
                if (ino->c_flags & CRDONLY) {
                        udata.u_error = EROFS;
-                       goto idrop;
+                       goto cantopen;
                }
        }
-       itmp = ino;
-       /* d_open may block and thus ino may become invalid as may
-          parent (but we don't need it again) */
-       if (isdevice(ino)
-           && d_open((int) ino->c_node.i_addr[0], flag) != 0) {
-               udata.u_error = ENXIO;
-               goto cantopen;
+
+       if (isdevice(ino)) {
+               itmp = ino;
+               /* d_open may block and thus ino may become invalid as may
+                  parent (but we don't need it again). It may also be changed
+                  by the call to dev_openi */
+
+               if (dev_openi(&itmp, flag) != 0)
+                       goto cantopen;
+
+               /* get the static pointer back */
+               ino = itmp;
+               /* May have changed */
+               of_tab[oftindex].o_inode = ino;
        }
-       /* get the static pointer back */
-       ino = itmp;
+
        if (trunc && getmode(ino) == F_REG) {
                if (f_trunc(ino))
                        goto idrop;
index 61e9ab7..37e2c66 100644 (file)
@@ -35,12 +35,6 @@ int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
        used(rawflag);
        used(flag);                     /* shut up compiler */
 
-       /* Minor == 0 means that it is the controlling tty of the process */
-       if (!minor)
-               minor = udata.u_ptab->p_tty;
-       if (!udata.u_ptab->p_tty)
-               udata.u_ptab->p_tty = minor;
-
        q = &ttyinq[minor];
        t = &ttydata[minor];
        nread = 0;
@@ -102,12 +96,6 @@ int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
        used(rawflag);
        used(flag);
 
-       /* Minor == 0 means that it is the controlling tty of the process */
-       if (!minor)
-               minor = udata.u_ptab->p_tty;
-       if (!udata.u_ptab->p_tty)
-               udata.u_ptab->p_tty = minor;
-
        t = &ttydata[minor];
 
        towrite = udata.u_count;
@@ -147,16 +135,9 @@ int tty_open(uint8_t minor, uint16_t flag)
 {
        struct tty *t;
 
-       /* FIXME : open/carrier logic is needed here, definitely before we
-          enable ptys */
-       /* Minor == 0 means that it is the controlling tty of the process */
-       /* FIXME: need to propogate this minor change back into the file handle
-          and inode somehow ??? */
-       if (!minor)
-               minor = udata.u_ptab->p_tty;
-       if (minor < 1 || minor > NUM_DEV_TTY) {
+       if (minor > NUM_DEV_TTY) {
                udata.u_error = ENODEV;
-               return (-1);
+               return -1;
        }
 
        t = &ttydata[minor];
@@ -167,11 +148,6 @@ int tty_open(uint8_t minor, uint16_t flag)
                return -1;
         }
 
-       /* If there is no controlling tty for the process, establish it */
-       if (!udata.u_ptab->p_tty && !t->pgrp && !(flag & O_NOCTTY)) {
-               udata.u_ptab->p_tty = minor;
-               t->pgrp = udata.u_ptab->p_pgrp;
-       }
        if (t->users) {
                t->users++;
                return 0;
@@ -195,14 +171,28 @@ int tty_open(uint8_t minor, uint16_t flag)
         return 0;
 }
 
+/* Post processing for a successful tty open */
+void tty_post(inoptr ino, uint8_t minor, uint8_t flag)
+{
+        struct tty *t = &ttydata[minor];
+       /* If there is no controlling tty for the process, establish it */
+       if (!udata.u_ptab->p_tty && !t->pgrp && !(flag & O_NOCTTY)) {
+               udata.u_ptab->p_tty = minor;
+               udata.u_ctty = ino;
+               t->pgrp = udata.u_ptab->p_pgrp;
+       }
+}
+
 int tty_close(uint8_t minor)
 {
         struct tty *t = &ttydata[minor];
         if (--t->users)
                 return 0;
        /* If we are closing the controlling tty, make note */
-       if (minor == udata.u_ptab->p_tty)
+       if (minor == udata.u_ptab->p_tty) {
                udata.u_ptab->p_tty = 0;
+               udata.u_ctty = NULL;
+        }
        t->pgrp = 0;
         /* If we were hung up then the last opener has gone away */
         t->flag &= ~TTYF_DEAD;
@@ -221,9 +211,7 @@ void tty_exit(void)
 int tty_ioctl(uint8_t minor, uarg_t request, char *data)
 {                              /* Data in User Space */
         struct tty *t;
-       if (!minor)
-               minor = udata.u_ptab->p_tty;
-       if (minor < 1 || minor > NUM_DEV_TTY + 1) {
+       if (minor > NUM_DEV_TTY + 1) {
                udata.u_error = ENODEV;
                return -1;
        }