]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.99.1 (December 21, 1992) 0.99.1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:08 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:08 +0000 (15:09 -0500)
Patch 1 addresses the following problems:
 - configuration. Hope there are no silly problems left..
 - inode.c: initialization changes (the missing NULL and some other
   minor fixes).
 - some SCSI tape driver patches (Kai M{kisara)
 - tcp/ip patches (Ross Biro, some code by me)
 - keyboard patches (mainly changed initialization - hope the keyboard
   lockups are gone).
 - completed /proc-fs: it should now contain all info needed by 'ps'
   (Micheal K Johnson).
 - various minor fixes (the minix-fs link overflow checking etc)

Patch1 also contains support for extended VC switching - this is for the
upcoming X11 that understands VC's.  One result of this is that console
redirection now redirects *only* messages actually sent to /dev/console
(aka /dev/tty0), not just to any foreground VC.  Wait for Xfree-1.2 to
be able to switch VC's while under X (yes, including several X-sessions
active at the same time..).

I hope there are still people out there that aren't too busy stuffing
themself with turkey to try out a new kernel release.  There is just
over a week left of this year, and I need feedback in order to be able
to release 1.0.

                Linus

PS.  Thanks to everybody who has sent me Christmas/New Year/Birthday
cards.  Some contained money, some didn't, and I enjoyed them all.
Thanks.

49 files changed:
.config
.version
Makefile
boot/bootsect.S
config.in
fs/exec.c
fs/inode.c
fs/isofs/.depend
fs/isofs/inode.c
fs/minix/namei.c
fs/proc/.depend
fs/proc/array.c
fs/proc/base.c
fs/proc/inode.c
include/linux/autoconf.h
include/linux/fs.h
include/linux/keyboard.h
include/linux/sys.h
include/linux/tty.h
init/main.c
kernel/FPU-emu/fpu_entry.c
kernel/blk_drv/blk.h
kernel/blk_drv/scsi/scsi_ioctl.c
kernel/blk_drv/scsi/sr_ioctl.c
kernel/blk_drv/scsi/st.c
kernel/blk_drv/scsi/st.h
kernel/chr_drv/.depend
kernel/chr_drv/console.c
kernel/chr_drv/keyboard.c
kernel/chr_drv/psaux.c
kernel/chr_drv/pty.c
kernel/chr_drv/serial.c
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c
kernel/chr_drv/vt.c
kernel/chr_drv/vt_kern.h
kernel/fork.c
kernel/printk.c
kernel/ptrace.c
net/Makefile
net/tcp/.depend
net/tcp/Makefile
net/tcp/arp.c
net/tcp/sock.c
net/tcp/tcp.c
net/tcp/tcp.h
net/tcp/timer.c
net/unix.c
tools/version.h

diff --git a/.config b/.config
index 9bae5f329e7685196cdd4d3be8c1cb00e8c58945..2cc80b62876c0550196d654c144fb9a8ca6d9535 100644 (file)
--- a/.config
+++ b/.config
@@ -7,8 +7,8 @@
 #
 CONFIG_BLK_DEV_HD = CONFIG_BLK_DEV_HD
 CONFIG_TCPIP = CONFIG_TCPIP
-CONFIG_PROFILE = CONFIG_PROFILE
 CONFIG_MAX_16M = CONFIG_MAX_16M
+CONFIG_M486 = CONFIG_M486
 
 #
 # SCSI support
index c739b42c4d2ce23786c5350641d0adbf5fa7d6b2..9e5feb5256930f3cae636754eef8a244ede164eb 100644 (file)
--- a/.version
+++ b/.version
@@ -1 +1 @@
-44
+46
index 42d893c3befb6e8ac513ed38a81afcb01fe90619..d740d50ef0686dff916ecd67b9a384336163ee9d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,11 @@
+#
+# Make "config" the default target if there is no configuration file
+#
+ifeq (.config,$(wildcard .config))
 include .config
+else
+CONFIGURATION = config
+endif
 
 #
 # ROOT_DEV specifies the default root-device when making the image.
@@ -69,6 +76,10 @@ SOUND_SUPPORT = -DKERNEL_SOUNDCARD -DDSP_BUFFSIZE=16384 -DSBC_IRQ=7 -DPAS_IRQ=5
 
 CFLAGS = -Wall -O6 -fomit-frame-pointer
 
+ifdef CONFIG_M486
+CFLAGS := $(CFLAGS) -m486
+endif
+
 #
 # if you want the ram-disk device, define this to be the
 # size in blocks.
@@ -112,20 +123,31 @@ lilo: Image
        /etc/lilo/install
 
 config:
+ifdef CONFIGURATION
+       @echo
+       @echo "You have no .config: running Configure"
+       @echo
+endif
        sh Configure < config.in
+ifdef CONFIGURATION
+       @echo
+       @echo "Configure successful. Try re-making (ignore the error that follows)"
+       @echo
+       exit 1
+endif
 
 linuxsubdirs: dummy
        @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE)) || exit; done
 
-Version:
+Version: dummy
        @./makever.sh
-       @echo \#define UTS_RELEASE \"0.99-`cat .version`\" > tools/version.h
+       @echo \#define UTS_RELEASE \"0.99.pl1-`cat .version`\" > tools/version.h
        @echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h
 
-Image: boot/bootsect boot/setup tools/system tools/build
+Image: $(CONFIGURATION) boot/bootsect boot/setup tools/system tools/build
        cp tools/system system.tmp
        strip system.tmp
        tools/build boot/bootsect boot/setup system.tmp $(ROOT_DEV) > Image
@@ -162,8 +184,8 @@ boot/setup: boot/setup.s
        $(AS86) -o boot/setup.o boot/setup.s
        $(LD86) -s -o boot/setup boot/setup.o
 
-boot/setup.s:  boot/setup.S include/linux/config.h
-       $(CPP) -traditional boot/setup.S -o boot/setup.s
+boot/setup.s:  boot/setup.S include/linux/config.h Makefile
+       $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/setup.S -o boot/setup.s
 
 boot/bootsect.s: boot/bootsect.S include/linux/config.h Makefile
        $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) boot/bootsect.S -o boot/bootsect.s
@@ -195,7 +217,7 @@ depend dep:
        for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done > .depend
        for i in $(SUBDIRS); do (cd $$i && $(MAKE) dep) || exit; done
 
-dummy:
+dummy: $(CONFIGURATION)
 
 #
 # include a dependency file if one exists
@@ -203,3 +225,4 @@ dummy:
 ifeq (.depend,$(wildcard .depend))
 include .depend
 endif
+
index d9a44b2f27e03ac49354045c9bca23a85a96986a..075c4bea645c4c91e09475bfd136ee0277c0727e 100644 (file)
@@ -78,8 +78,6 @@ go:   mov     ax,cs
 
        mov     ds,ax
        mov     es,ax
-       push    ax
-
        mov     ss,ax           ! put stack at INITSEG:0x4000-12.
        mov     sp,dx
 /*
@@ -121,7 +119,7 @@ go: mov     ax,cs
        seg fs
        mov     2(bx),es
 
-       pop     ax
+       mov     ax,cs
        mov     fs,ax
        mov     gs,ax
        
index f81aca03c491708aeea6b35336d3700bfb67ce6f..051413969d8fd8ff2738e529a0d20406049682ae 100644 (file)
--- a/config.in
+++ b/config.in
@@ -10,6 +10,8 @@ Kernel profiling support
 CONFIG_PROFILE y/n n
 Limit to memory to low 16MB
 CONFIG_MAX_16M y/n y
+Use -m486 flag for 486-specific optimizations
+CONFIG_M486 y/n y
 :
 SCSI support
 .
@@ -27,9 +29,9 @@ CONFIG_BLK_DEV_SR y/n y
 .
 SCSI low-level drivers
 .
-Adaptek AHA1542 support
+Adaptec AHA1542 support
 CONFIG_SCSI_AHA1542 y/n y
-Adaptek AHA1740 support
+Adaptec AHA1740 support
 CONFIG_SCSI_AHA1740 y/n y
 Always IN support
 CONFIG_SCSI_ALWAYS y/n y
@@ -67,7 +69,7 @@ Accent Async 4 serial support
 CONFIG_ACCENT_ASYNC y/n n
 Logitech busmouse support
 CONFIG_BUSMOUSE y/n n
-PS/2 mouse (aka 'auxilliary device') support
+PS/2 mouse (aka 'auxiliary device') support
 CONFIG_PSMOUSE y/n n
 MicroSoft busmouse support
 CONFIG_MS_BUSMOUSE y/n n
index 62ea5944e755aabb57048da928fdad6057716b71..2942228d2ecb690e247688a0ae6b73e60a2e0a1f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -376,17 +376,18 @@ static void read_omagic(struct inode *inode, int bytes)
        if (inode->i_sb)
                block_size = inode->i_sb->s_blocksize;
        while (bytes > 0) {
-               if (!(blkno = bmap(inode, blk)))
-                       sys_exit(-1);
-               if (!(bh = bread(inode->i_dev, blkno, block_size)))
-                       sys_exit(-1);
                n = (blk ? block_size : block_size - sizeof(struct exec));
                if (bytes < n)
                        n = bytes;
-
-               memcpy_tofs(dest, (blk ? bh->b_data :
+               blkno = bmap(inode, blk);
+               if (blkno) {
+                       bh = bread(inode->i_dev, blkno, block_size);
+                       if (!bh)
+                               sys_exit(-1);
+                       memcpy_tofs(dest, (blk ? bh->b_data :
                                bh->b_data + sizeof(struct exec)), n);
-               brelse(bh);
+                       brelse(bh);
+               }
                ++blk;
                dest += n;
                bytes -= n;
index d1eb15e19516aba5c5da2bc50097354299e21400..92ed94ffe4b48086b7d7fb305a50f33ea6f6aad8 100644 (file)
 
 #include <asm/system.h>
 
-static struct inode inode_table[NR_INODE];
-static struct inode * last_inode = inode_table;
-static struct wait_queue * inode_wait;
+static struct inode * inode_table;
+static struct inode * last_inode;
+static struct wait_queue * inode_wait = NULL;
 
-void inode_init(void)
+unsigned long inode_init(unsigned long start, unsigned long end)
 {
-       memset(inode_table,0,sizeof(inode_table));      
+       start += 0x0000000f;
+       start &= 0xfffffff0;
+       inode_table = (struct inode *) start;
+       last_inode = inode_table;
+       start = (unsigned long) (inode_table + NR_INODE);
+       memset(inode_table,0,NR_INODE*sizeof(struct inode));
+       return start;
 }
 
 static void __wait_on_inode(struct inode *);
index 34d1856fc0d12cf2c40a6ba15ebe9383a268745f..7c8a4759db38b361c17294934f217822fb208449 100644 (file)
@@ -53,6 +53,19 @@ file.o : file.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/includ
   /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
   /usr/include/linux/iso_fs.h /usr/include/linux/fcntl.h /usr/include/linux/errno.h \
   /usr/include/linux/stat.h /usr/include/linux/locks.h 
+inode.o : inode.c /usr/include/linux/config.h /usr/include/linux/autoconf.h \
+  /usr/include/linux/stat.h /usr/include/linux/sched.h /usr/include/linux/head.h \
+  /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
+  /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
+  /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
+  /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
+  /usr/include/linux/nfs.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
+  /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
+  /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
+  /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/iso_fs.h \
+  /usr/include/linux/string.h /usr/include/linux/locks.h /usr/include/asm/system.h \
+  /usr/include/asm/segment.h /usr/include/linux/errno.h 
 namei.o : namei.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
   /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/types.h \
   /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
index 57981c1e0ef3ce6542cf69bc946f72b4a036038a..39b00fabe4f9bf4904e875b5a451c7c4f40935fb 100644 (file)
 #include <asm/segment.h>
 #include <linux/errno.h>
 
-#ifndef CONFIG_BLK_DEV_SR
-#error The iso9660 filesystem can only be used with CDROM.
-#endif
-
 extern int check_cdrom_media_change(int, int);
 
 #ifdef LEAK_CHECK
index 45242f74f5b01be703630c50ff7ea81c1550c344..ec6cb63eff7c142a717d8dc5e73537eb685dd046 100644 (file)
@@ -304,6 +304,10 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
                iput(dir);
                return -EEXIST;
        }
+       if (dir->i_nlink > 250) {
+               iput(dir);
+               return -EMLINK;
+       }
        inode = minix_new_inode(dir);
        if (!inode) {
                iput(dir);
@@ -695,6 +699,9 @@ start_up:
                        goto end_rename;
                if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
                        goto end_rename;
+               retval = -EMLINK;
+               if (new_dir->i_nlink > 250)
+                       goto end_rename;
        }
        if (!new_bh)
                new_bh = minix_add_entry(new_dir,new_name,new_len,&new_de);
index 0bf3700b372b404ca5b34ced7d3ed46d17420a08..2aec1acfba4002002144c1c6787b7825a7199d9e 100644 (file)
@@ -7,7 +7,8 @@ array.o : array.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/inc
   /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
   /usr/include/linux/mm.h /usr/include/linux/kernel.h /usr/include/linux/signal.h \
   /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
-  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/asm/segment.h \
+  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/tty.h \
+  /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/asm/segment.h \
   /usr/include/asm/io.h 
 base.o : base.c /usr/include/asm/segment.h /usr/include/linux/errno.h /usr/include/linux/sched.h \
   /usr/include/linux/head.h /usr/include/linux/fs.h /usr/include/linux/limits.h \
index 3d8db0be26452a7326fc16f941d77831e9c598f5..f9e4b0ea0cdf74bb082e2ed2a790bf9d0bc4d7a1 100644 (file)
@@ -3,12 +3,15 @@
  *
  *  Copyright (C) 1992  by Linus Torvalds
  *  based on ideas by Darren Senn
+ *
+ *  stat,statm extensions by Michael K. Johnson, johnsonm@stolaf.edu
  */
 
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/tty.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
+#define        KSTK_EIP(stack) (((char *)stack)[1019])
+#define        KSTK_ESP(stack) (((char *)stack)[1022])
+
+#define        _SSIZE(stack)   (TASK_SIZE - KSTK_ESP(stack))
+#define        SSIZE(stack)    (KSTK_ESP(stack) ? _SSIZE(stack) : 0)
+
+#define        VSIZE(task,stack) ((task)->brk + 1023 + SSIZE(stack))
+#define        SIZE(task,stack)  (((task)->brk - (task)->end_code + 1023 + \
+                         SSIZE(stack)) / 1024)
+
+
 static int get_loadavg(char * buffer)
 {
        int a, b, c;
@@ -129,6 +143,8 @@ static int get_arg(int pid, char * buffer)
 static int get_stat(int pid, char * buffer)
 {
        struct task_struct ** p = get_task(pid);
+       unsigned long sigignore=0, sigcatch=0, bit=1;
+       int i;
        char state;
 
        if (!p || !*p)
@@ -137,14 +153,101 @@ static int get_stat(int pid, char * buffer)
                state = '.';
        else
                state = "RSDZTD"[(*p)->state];
-       return sprintf(buffer,"%d (%s) %c %d %d %d %d\n",
+       for(i=0; i<32; ++i) {
+               switch((int) (*p)->sigaction[i].sa_handler) {
+               case 1: sigignore |= bit; break;
+               case 0: break;
+               default: sigcatch |= bit;
+               } bit <<= 1;
+       }
+       return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
+%u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
+%d %d %d %u\n",
                pid,
                (*p)->comm,
                state,
                (*p)->p_pptr->pid,
                (*p)->pgrp,
                (*p)->session,
-               (*p)->tty);
+               (*p)->tty,
+               ((*p)->tty == -1) ? -1 :
+                      tty_table[(*p)->tty]->pgrp,
+               (*p)->flags,
+               (*p)->min_flt,
+               (*p)->cmin_flt,
+               (*p)->maj_flt,
+               (*p)->cmaj_flt,
+               (*p)->utime,
+               (*p)->stime,
+               (*p)->cutime,
+               (*p)->cstime,
+               (*p)->counter,  /* this is the kernel priority ---
+                                  subtract 30 in your user-level program. */
+               (*p)->priority, /* this is the nice value ---
+                                  subtract 15 in your user-level program. */
+               (*p)->timeout,
+               (*p)->it_real_value,
+               (*p)->start_time,
+               VSIZE((*p),(*p)->kernel_stack_page),
+               (*p)->rss, /* you might want to shift this left 3 */
+               (*p)->rlim[RLIMIT_RSS].rlim_cur,
+               (*p)->start_code,
+               (*p)->end_code,
+               (*p)->start_stack,
+               KSTK_ESP((*p)->kernel_stack_page),
+               KSTK_EIP((*p)->kernel_stack_page),
+               (*p)->signal,
+               (*p)->blocked,
+               sigignore,
+               sigcatch,
+               (*p)->tss.eip);
+}
+
+static int get_statm(int pid, char * buffer)
+{
+       struct task_struct ** p = get_task(pid);
+       int i, tpag;
+       int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
+       unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
+
+       if (!p || !*p)
+               return 0;
+       tpag = (*p)->end_code / PAGE_SIZE;
+       if ((*p)->state != TASK_ZOMBIE) {
+         pagedir = (void *)((*p)->tss.cr3 + ((*p)->start_code >> 20));
+         for (i = 0; i < 0x300; ++i) {
+           if ((ptbl = pagedir[i]) == 0) {
+             tpag -= 1024;
+             continue;
+           }
+           buf = (void *)(ptbl & 0xfffff000);
+           for (pte = buf; pte < (buf + 1024); ++pte) {
+             if (*pte != 0) {
+               ++size;
+               if (*pte & 1) {
+                 ++resident;
+                 if (tpag > 0)
+                   ++trs;
+                 else
+                   ++drs;
+                 if (i >= 15 && i < 0x2f0) {
+                   ++lrs;
+                   if (*pte & 0x40)
+                     ++dt;
+                   else
+                     --drs;
+                 }
+                 map_nr = MAP_NR(*pte);
+                 if (map_nr < (high_memory / 4096) && mem_map[map_nr] > 1)
+                   ++share;
+               }
+             }
+             --tpag;
+           }
+         }
+       }
+       return sprintf(buffer,"%d %d %d %d %d %d %d\n",
+                      size, resident, share, trs, lrs, drs, dt);
 }
 
 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
@@ -181,6 +284,9 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c
                case 11:
                        length = get_stat(pid, page);
                        break;
+               case 12:
+                       length = get_statm(pid, page);
+                       break;
                default:
                        free_page((unsigned long) page);
                        return -EBADF;
index fc37cc4a92888fd85fff33e4c30dc84e6604ba4a..24e821013b51493f1a3b375431fc6115e39d9e93 100644 (file)
@@ -59,7 +59,8 @@ static struct proc_dir_entry base_dir[] = {
        { 8,3,"lib" },
        { 9,7,"environ" },
        { 10,7,"cmdline" },
-       { 11,4,"stat" }
+       { 11,4,"stat" },
+       { 12,5,"statm" }
 };
 
 #define NR_BASE_DIRENTRY ((sizeof (base_dir))/(sizeof (base_dir[0])))
index 9f206b073ba5404778585ae918f767656edad73d..07ceb81e85e8f5af1df5674eeea8a18609961b70 100644 (file)
@@ -143,6 +143,7 @@ void proc_read_inode(struct inode * inode)
                case 9:
                case 10:
                case 11:
+               case 12:
                        inode->i_mode = S_IFREG | 0444;
                        inode->i_op = &proc_array_inode_operations;
                        return;
index 172aac351f9d90d44d1d4ab17ef86fea6b164730..e6db1e5dbd5206109213fc776c410d3d2c270e05 100644 (file)
@@ -7,8 +7,8 @@
  */
 #define CONFIG_BLK_DEV_HD 1
 #define CONFIG_TCPIP 1
-#define CONFIG_PROFILE 1
 #define CONFIG_MAX_16M 1
+#define CONFIG_M486 1
 
 /*
  * SCSI support
index c00154d214c776d45379a527d6227e205d35a193..18143767659606579301131332a29a0688842b2e 100644 (file)
@@ -23,7 +23,7 @@
 #undef NR_OPEN
 #define NR_OPEN 256
 
-#define NR_INODE 128
+#define NR_INODE 256
 #define NR_FILE 128
 #define NR_SUPER 16
 #define NR_HASH 997
@@ -66,7 +66,7 @@
 #define WRITEA 3       /* "write-ahead" - silly, but somewhat useful */
 
 extern void buffer_init(void);
-extern void inode_init(void);
+extern unsigned long inode_init(unsigned long start, unsigned long end);
 
 #define MAJOR(a) (((unsigned)(a))>>8)
 #define MINOR(a) ((a)&0xff)
index b3f01b6ec56b7e6149af92b076db5eb5f56f6727..dfae10fb9e0461f22cfe3f44f0a4fe5ee90dfd8b 100644 (file)
@@ -23,8 +23,19 @@ extern unsigned long kbd_flags;
 #define KG_ALT         4
 #define KG_ALTGR       5
 #define KG_CAPSLOCK    6
-#define KG_E0          7
-#define KG_E1          8
+
+/*
+ * "dead" keys - prefix key values that are valid only for the next
+ * character code (sticky shift, E0/E1 special scancodes, diacriticals)
+ */
+extern unsigned long kbd_dead_keys;
+extern unsigned long kbd_prev_dead_keys;
+
+/*
+ * these are the hardcoded dead key flags
+ */
+#define KGD_E0         0
+#define KGD_E1         1
 
 /*
  * kbd->xxx contains the VC-local things (flag settings etc..)
@@ -80,6 +91,26 @@ extern inline void chg_kbd_flag(int flag)
        kbd_flags ^= 1 << flag;
 }
 
+extern inline int kbd_dead(int flag)
+{
+       return kbd_prev_dead_keys & (1 << flag);
+}
+
+extern inline void set_kbd_dead(int flag)
+{
+       kbd_dead_keys |= 1 << flag;
+}
+
+extern inline void clr_kbd_dead(int flag)
+{
+       kbd_dead_keys &= ~(1 << flag);
+}
+
+extern inline void chg_kbd_dead(int flag)
+{
+       kbd_dead_keys ^= 1 << flag;
+}
+
 extern inline int vc_kbd_flag(struct kbd_struct * kbd, int flag)
 {
        return ((kbd->flags >> flag) & 1);
index c5c831c084a75ba7dcd5550fa08917d0da93b10c..45ae421ebc395442c7916264ad1775583ae84891 100644 (file)
@@ -134,14 +134,14 @@ sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
 sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
 sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
 sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
-sys_gettimeofday,  sys_settimeofday, sys_getgroups, sys_setgroups,
+sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
 sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
-sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap,
-sys_truncate, sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority,
-sys_setpriority, sys_profil, sys_statfs, sys_fstatfs, sys_ioperm,
-sys_socketcall, sys_syslog, sys_setitimer, sys_getitimer, sys_newstat,
-sys_newlstat, sys_newfstat, sys_newuname, sys_iopl, sys_vhangup,
-sys_idle, sys_vm86, sys_wait4, sys_swapoff, sys_sysinfo };
+sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_truncate,
+sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
+sys_profil, sys_statfs, sys_fstatfs, sys_ioperm, sys_socketcall,
+sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
+sys_newfstat, sys_newuname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
+sys_wait4, sys_swapoff, sys_sysinfo };
 
 /* So we don't have to do any more manual updating.... */
 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
index 0b26653a0478cf6ab3a276bd80e9b0db886924cf..e529d7ff4f7a3db5abfa82f65c8e2100193c19a3 100644 (file)
@@ -285,6 +285,7 @@ extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern int kill_pg(int pgrp, int sig, int priv);
 extern int kill_sl(int sess, int sig, int priv);
+extern void tty_hangup(struct tty_struct * tty);
 extern void do_SAK(struct tty_struct *tty);
 
 /* tty write functions */
index 89b351e40b5a88332eb5c6914e75ca9a1ef78e08..cb47e84cb74fd83d038f3db07de6074c45fcdfb4 100644 (file)
@@ -133,7 +133,7 @@ static unsigned long memory_start = 0; /* After mem_init, stores the */
 static unsigned long memory_end = 0;
 static unsigned long low_memory_start = 0;
 
-static char * argv_init[MAX_INIT_ARGS+2] = { "/bin/init", NULL, };
+static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=console", NULL, };
 
 static char * argv_rc[] = { "/bin/sh", NULL };
@@ -238,9 +238,9 @@ void start_kernel(void)
 #ifdef CONFIG_SCSI
        memory_start = scsi_dev_init(memory_start,memory_end);
 #endif
+       memory_start = inode_init(memory_start,memory_end);
        mem_init(low_memory_start,memory_start,memory_end);
        buffer_init();
-       inode_init();
        time_init();
        floppy_init();
        sock_init();
index d1c8934f8e63c9db0bd03b9bddcee27ea17b56f0..3dc9c64f749ff2c9154cc593dac2f312893e7e30 100644 (file)
@@ -288,6 +288,8 @@ void __math_abort(struct info * info, unsigned int signal)
 
 void math_emulate(long arg)
 {
+  printk("math-meulation not enabled and no coprocessor found.\n");
+  printk("killing %s.\n",current->comm);
   send_sig(SIGFPE,current,1);
   schedule();
 }
index 792cae9bf059484174691ed1179fef5871bb0d49..dbd9718b0721fc77277dab77cc32783ca0a44c09 100644 (file)
@@ -152,6 +152,8 @@ extern int ramdisk_size;
 
 #endif
 
+#if (MAJOR_NR != 9)
+
 #ifndef CURRENT
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
 #endif
@@ -259,3 +261,4 @@ static void end_request(int uptodate)
 #endif
 
 #endif
+#endif
index 8516a03e8cc32d20dbb19bdfd82dfe9bec18f8e6..b8a5661461a423d18b7d5ae1e977655246ba989d 100644 (file)
@@ -216,7 +216,7 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
 {
         char scsi_cmd[10];
 
-       if ((cmd != 0 && dev->id > NR_SCSI_DEVICES))
+       if ((cmd != 0 && dev->index > NR_SCSI_DEVICES))
                return -ENODEV;
        if ((cmd == 0 && dev->host_no > max_scsi_hosts))
                return -ENODEV;
index bffa55e068f102c64d206ae9a2616914b30b1707..af9b4dc0cd1886a83334b7b43aacfa4bdb620db9 100644 (file)
@@ -97,6 +97,7 @@ int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsign
        int result, target;
 
        target = MINOR(dev);
+       if (target >= NR_SR) return -ENODEV;
 
        switch (cmd) 
                {
index 3ff1abb2e14e36015eb92679ee5ba8d43ac48f0f..9ede064b64f28af6c686e233dab0796fe0053cd2 100644 (file)
@@ -30,7 +30,7 @@
 
   Kai Makisara, Nov 9, 1992  email makisara@vtinsx.ins.vtt.fi or
                                     Kai.Makisara@vtt.fi
-  Last changes Dec 6, 1992.
+  Last changes Dec 19, 1992.
 */
 
 #include <linux/fs.h>
    before command completion. */
 /* #define ST_NOWAIT */
 
+/* Uncomment the following if you want the tape to be positioned correctly
+   within file after close (the tape is positioned correctly with respect
+   to the filemarks even wihout ST_IN_FILE_POS defined */
+/* #define ST_IN_FILE_POS */
+
 /* #define DEBUG */
 
-#define ST_TIMEOUT 2000
+#define ST_TIMEOUT 6000
 #define ST_LONG_TIMEOUT 200000
 
 /* Number of ST_BLOCK_SIZE blocks in the buffers */
@@ -519,9 +524,13 @@ static void scsi_tape_close(struct inode * inode, struct file * filp)
       printk("st%d: Buffer flushed, EOF written\n", dev);
 #endif
     }
-    else if (!rewind && scsi_tapes[dev].eof && !scsi_tapes[dev].eof_hit)
-      st_int_ioctl(inode, filp, MTBSF, 1);
-               /* Back over the EOF hit inadvertently */
+    else if (!rewind) {
+      if ((scsi_tapes[dev].eof == 1) && !scsi_tapes[dev].eof_hit)
+       st_int_ioctl(inode, filp, MTBSF, 1); /* Back over the EOF hit */
+#ifdef ST_IN_FILE_POS
+      flush_buffer(inode, filp, 0);
+#endif
+    }
 
     if (rewind)
       st_int_ioctl(inode, filp, MTREW, 1);
@@ -701,12 +710,9 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
       printk("st%d: EOF flag up. Bytes %d\n", dev,
             scsi_tapes[dev].buffer->buffer_bytes);
 #endif
-    if ((scsi_tapes[dev].buffer->buffer_bytes == 0) && scsi_tapes[dev].eof) {
-      if (scsi_tapes[dev].eof == 1)
-       return 0;
-      else /* EOM or blank check */
-       return (-EIO);
-    }
+    if ((scsi_tapes[dev].buffer->buffer_bytes == 0) &&
+       scsi_tapes[dev].eof == 2)  /* EOM or Blank Check */
+      return (-EIO);
 
     scsi_tapes[dev].rw = 1;
 
@@ -714,7 +720,8 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
 
     for (total = 0; total < count; ) {
 
-      if (scsi_tapes[dev].buffer->buffer_bytes == 0 && scsi_tapes[dev].eof == 0) {
+      if (scsi_tapes[dev].buffer->buffer_bytes == 0 &&
+         scsi_tapes[dev].eof == 0) {
 
        memset(cmd, 0, 10);
        cmd[0] = READ_6;
@@ -734,6 +741,7 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
        if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
 
        scsi_tapes[dev].buffer->read_pointer = 0;
+       scsi_tapes[dev].eof_hit = 0;
 
        if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) {
 #ifdef DEBUG
@@ -796,8 +804,10 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
          }
        }
        else
-         scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->buffer_size;
-      } /* if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) */
+         scsi_tapes[dev].buffer->buffer_bytes =
+           scsi_tapes[dev].buffer->buffer_size;
+      } /* if (scsi_tapes[dev].buffer->buffer_bytes == 0 &&
+          scsi_tapes[dev].eof == 0) */
 
       if (scsi_tapes[dev].buffer->buffer_bytes > 0) {
 #ifdef DEBUG
@@ -818,10 +828,11 @@ int st_read(struct inode * inode, struct file * filp, char * buf, int count)
       else if (scsi_tapes[dev].eof) {
        scsi_tapes[dev].eof_hit = 1;
        SCpnt->request.dev = -1;  /* Mark as not busy */
-       if (total)
-         return total;
-       else
+       if (total == 0 && scsi_tapes[dev].eof == 1)
+         scsi_tapes[dev].eof = 0;
+       if (total == 0 && scsi_tapes[dev].eof == 2)
          return (-EIO);
+       return total;
       }
 
     } /* for (total = 0; total < count; ) */
@@ -956,7 +967,7 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
        cmd[0] = SPACE;
        cmd[1] = 3;
 #ifdef DEBUG
-       printk("st%d: Spacing to end of tape media.\n", dev);
+       printk("st%d: Spacing to end of recorded medium.\n", dev);
 #endif
        break; 
      case MTERASE:
@@ -1050,6 +1061,8 @@ static int st_int_ioctl(struct inode * inode,struct file * file,
    if (!ioctl_result) {
      if (cmd_in == MTBSFM)
        ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
+     else if (cmd_in == MTFSFM)
+       ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
      else if (cmd_in == MTSETBLK) {
        scsi_tapes[dev].block_size = arg;
        scsi_tapes[dev].buffer->buffer_blocks =
index e5c9b7bd6f5f9904c2df7cb16bb829683e8fdadf..1df386c409048f91a493242a06edea12c071b026 100644 (file)
@@ -27,10 +27,10 @@ typedef struct {
   Scsi_Device* device;
   unsigned dirty:1;
   unsigned rw:2;
-  unsigned eof:1;
+  unsigned eof:2;
   unsigned write_prot:1;
   unsigned in_use:1;
-  unsigned eof_hit:2;
+  unsigned eof_hit:1;
   ST_buffer * buffer;
   int block_size;
   int min_block;
index ec2af3d9e42e043c1355d522e020f85f3b66331a..cbfd2d073f11ca81db7c3f541af3328bcab7c365 100644 (file)
@@ -36,7 +36,7 @@ console.o : console.c /usr/include/linux/sched.h /usr/include/linux/head.h /usr/
   /usr/include/linux/termios.h /usr/include/asm/system.h /usr/include/linux/config.h \
   /usr/include/linux/autoconf.h /usr/include/linux/string.h /usr/include/linux/errno.h \
   /usr/include/linux/kd.h /usr/include/linux/keyboard.h /usr/include/asm/io.h \
-  /usr/include/asm/segment.h vt_kern.h 
+  /usr/include/asm/segment.h vt_kern.h /usr/include/linux/vt.h 
 keyboard.o : keyboard.c /usr/include/linux/sched.h /usr/include/linux/head.h \
   /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
   /usr/include/linux/types.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
@@ -143,9 +143,9 @@ tty_io.o : tty_io.c /usr/include/linux/types.h /usr/include/linux/errno.h /usr/i
   /usr/include/linux/kernel.h /usr/include/linux/time.h /usr/include/linux/param.h \
   /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
   /usr/include/linux/tty.h /usr/include/linux/termios.h /usr/include/asm/system.h \
-  /usr/include/linux/ctype.h /usr/include/linux/kd.h /usr/include/linux/string.h \
-  /usr/include/linux/keyboard.h /usr/include/asm/segment.h /usr/include/asm/bitops.h \
-  vt_kern.h 
+  /usr/include/linux/timer.h /usr/include/linux/ctype.h /usr/include/linux/kd.h \
+  /usr/include/linux/string.h /usr/include/linux/keyboard.h /usr/include/asm/segment.h \
+  /usr/include/asm/bitops.h vt_kern.h /usr/include/linux/vt.h 
 tty_ioctl.o : tty_ioctl.c /usr/include/linux/types.h /usr/include/linux/termios.h \
   /usr/include/linux/errno.h /usr/include/linux/sched.h /usr/include/linux/head.h \
   /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
index a3b5f96666877d0eabde6d329dde84c928d66359..2d377ef09f718208893b67e4e095be86deb419c6 100644 (file)
@@ -170,7 +170,10 @@ static int console_blanked = 0;
 #define        halfcolor       (vc_cons[currcons].vc_halfcolor)
 #define kbdmode                (vc_cons[currcons].vc_kbdmode)
 #define tab_stop       (vc_cons[currcons].vc_tab_stop)
+#define vcmode         (vt_cons[currcons].vc_mode)
 #define vtmode         (vt_cons[currcons].vt_mode)
+#define vtpid          (vt_cons[currcons].vt_pid)
+#define vtnewvt                (vt_cons[currcons].vt_newvt)
 
 #define set_kbd(x) set_vc_kbd_flag(kbd_table+currcons,x)
 #define clr_kbd(x) clr_vc_kbd_flag(kbd_table+currcons,x)
@@ -285,7 +288,7 @@ static void set_origin(int currcons)
 {
        if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
                return;
-       if (currcons != fg_console || console_blanked || vtmode == KD_GRAPHICS)
+       if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
                return;
        cli();
        outb_p(12, video_port_reg);
@@ -1194,7 +1197,7 @@ void con_write(struct tty_struct * tty)
                                state = ESnormal;
                }
        }
-       if (vtmode == KD_GRAPHICS)
+       if (vcmode == KD_GRAPHICS)
                return;
        set_cursor(currcons);
 }
@@ -1203,7 +1206,7 @@ void do_keyboard_interrupt(void)
 {
        TTY_READ_FLUSH(TTY_TABLE(0));
        timer_active &= ~(1<<BLANK_TIMER);
-       if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
+       if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
                return;
        if (console_blanked) {
                timer_table[BLANK_TIMER].expires = 0;
@@ -1311,7 +1314,14 @@ long con_init(long kmem_start)
                pos = origin = video_mem_start = base;
                scr_end = video_mem_end = (base += screen_size);
                vc_scrbuf[currcons] = (unsigned short *) origin;
-               vtmode          = KD_TEXT;
+               vcmode          = KD_TEXT;
+               vtmode.mode     = VT_AUTO;
+               vtmode.waitv    = 0;
+               vtmode.relsig   = 0;
+               vtmode.acqsig   = 0;
+               vtmode.frsig    = 0;
+               vtpid           = -1;
+               vtnewvt         = -1;
                clr_kbd(kbdraw);
                def_color       = 0x07;   /* white */
                ulcolor         = 0x0f;   /* bold white */
@@ -1360,6 +1370,8 @@ static void set_scrmem(int currcons)
 
 void blank_screen(void)
 {
+       if (console_blanked)
+               return;
        timer_table[BLANK_TIMER].fn = unblank_screen;
        get_scrmem(fg_console);
        hide_cursor(fg_console);
@@ -1369,6 +1381,8 @@ void blank_screen(void)
 
 void unblank_screen(void)
 {
+       if (!console_blanked)
+               return;
        timer_table[BLANK_TIMER].fn = blank_screen;
        if (blankinterval) {
                timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
@@ -1463,7 +1477,7 @@ void console_print(const char * b)
                pos+=2;
        }
        set_cursor(currcons);
-       if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
+       if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
                return;
        timer_active &= ~(1<<BLANK_TIMER);
        if (console_blanked) {
@@ -1483,5 +1497,7 @@ int con_open(struct tty_struct *tty, struct file * filp)
 {
        tty->write = con_write;
        tty->ioctl = vt_ioctl;
+       if (tty->line > NR_CONSOLES)
+               return -ENODEV;
        return 0;
 }
index 73a71e91fc35c966cbeac7cbe9af6f6a8f32ac1a..5f43db0f3034622426f17b19b44ef83ba9e94d6e 100644 (file)
@@ -32,6 +32,8 @@ extern void ctrl_alt_del(void);
 extern void change_console(unsigned int new_console);
 
 unsigned long kbd_flags = 0;
+unsigned long kbd_dead_keys = 0;
+unsigned long kbd_prev_dead_keys = 0;
 
 struct kbd_struct kbd_table[NR_CONSOLES];
 static struct kbd_struct * kbd = kbd_table;
@@ -54,59 +56,54 @@ static struct pt_regs * pt_regs;
 static void keyboard_interrupt(int int_pt_regs)
 {
        static unsigned char rep = 0xff;
-       unsigned char scancode, x;
+       unsigned char scancode;
 
        pt_regs = (struct pt_regs *) int_pt_regs;
-       scancode=inb_p(0x60);
-       x=inb_p(0x61);
-       outb_p(x|0x80, 0x61);
-       outb_p(x&0x7f, 0x61);
-       if (scancode == 0xe0)
-               set_kbd_flag(KG_E0);
-       else if (scancode == 0xe1)
-               set_kbd_flag(KG_E1);
-       tty = TTY_TABLE(0);
-       kbd = kbd_table + fg_console;
-       if (vc_kbd_flag(kbd,VC_RAW)) {
-               kbd_flags = 0;
-               put_queue(scancode);
-               do_keyboard_interrupt();
-               return;
-       }
-       if (scancode == 0xe0 || scancode == 0xe1)
-               return;
-       /*
-        *  The keyboard maintains its own internal caps lock and num lock
-        *  statuses. In caps lock mode E0 AA precedes make code and E0 2A
-        *  follows break code. In num lock mode, E0 2A precedes make
-        *  code and E0 AA follows break code. We do our own book-keeping,
-        *  so we will just ignore these.
-        */
-       if (kbd_flag(KG_E0) && (scancode == 0x2a || scancode == 0xaa)) {
-               clr_kbd_flag(KG_E0);
-               clr_kbd_flag(KG_E1);
-               return;
-       }
-       /*
-        *  Repeat a key only if the input buffers are empty or the
-        *  characters get echoed locally. This makes key repeat usable
-        *  with slow applications and unders heavy loads.
-        */
-       if (scancode == rep) {
-               if (!(vc_kbd_flag(kbd,VC_REPEAT) && tty &&
-                          (L_ECHO(tty) ||
-                           (EMPTY(&tty->secondary) &&
-                            EMPTY(&tty->read_q))))) {
-                       clr_kbd_flag(KG_E0);
-                       clr_kbd_flag(KG_E1);
-                       return;
+       while (inb_p(0x64) & 1) {
+               kbd_prev_dead_keys |= kbd_dead_keys;
+               if (!kbd_dead_keys)
+                       kbd_prev_dead_keys = 0;
+               kbd_dead_keys = 0;
+               scancode = inb_p(0x60);
+               tty = TTY_TABLE(0);
+               kbd = kbd_table + fg_console;
+               if (vc_kbd_flag(kbd,VC_RAW)) {
+                       kbd_flags = 0;
+                       put_queue(scancode);
+                       continue;
+               }
+               if (scancode == 0xe0) {
+                       set_kbd_dead(KGD_E0);
+                       continue;
+               } else if (scancode == 0xe1) {
+                       set_kbd_dead(KGD_E1);
+                       continue;
                }
+               /*
+                *  The keyboard maintains its own internal caps lock and num lock
+                *  statuses. In caps lock mode E0 AA precedes make code and E0 2A
+                *  follows break code. In num lock mode, E0 2A precedes make
+                *  code and E0 AA follows break code. We do our own book-keeping,
+                *  so we will just ignore these.
+                */
+               if (kbd_dead(KGD_E0) && (scancode == 0x2a || scancode == 0xaa))
+                       continue;
+               /*
+                *  Repeat a key only if the input buffers are empty or the
+                *  characters get echoed locally. This makes key repeat usable
+                *  with slow applications and unders heavy loads.
+                */
+               if (scancode == rep) {
+                       if (!(vc_kbd_flag(kbd,VC_REPEAT) && tty &&
+                                  (L_ECHO(tty) ||
+                                   (EMPTY(&tty->secondary) &&
+                                    EMPTY(&tty->read_q)))))
+                               continue;
+               }
+               rep = scancode;
+               key_table[scancode](scancode);
        }
-       rep = scancode;
-       key_table[scancode](scancode);
        do_keyboard_interrupt();
-       clr_kbd_flag(KG_E0);
-       clr_kbd_flag(KG_E1);
 }
 
 static void put_queue(int ch)
@@ -147,7 +144,7 @@ static void puts_queue(char *cp)
 
 static void ctrl(int sc)
 {
-       if (kbd_flag(KG_E0))
+       if (kbd_dead(KGD_E0))
                set_kbd_flag(KG_RCTRL);
        else
                set_kbd_flag(KG_LCTRL);
@@ -155,7 +152,7 @@ static void ctrl(int sc)
 
 static void alt(int sc)
 {
-       if (kbd_flag(KG_E0))
+       if (kbd_dead(KGD_E0))
                set_kbd_flag(KG_ALTGR);
        else
                set_kbd_flag(KG_ALT);
@@ -163,7 +160,7 @@ static void alt(int sc)
 
 static void unctrl(int sc)
 {
-       if (kbd_flag(KG_E0))
+       if (kbd_dead(KGD_E0))
                clr_kbd_flag(KG_RCTRL);
        else
                clr_kbd_flag(KG_LCTRL);
@@ -171,7 +168,7 @@ static void unctrl(int sc)
 
 static void unalt(int sc)
 {
-       if (kbd_flag(KG_E0))
+       if (kbd_dead(KGD_E0))
                clr_kbd_flag(KG_ALTGR);
        else {
                clr_kbd_flag(KG_ALT);
@@ -218,6 +215,8 @@ static void uncaps(int sc)
 
 static void show_ptregs(void)
 {
+       if (!pt_regs)
+               return;
        printk("\nEIP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
        if (pt_regs->cs & 3)
                printk(" ESP: %04x:%08x",0xffff & pt_regs->cs,pt_regs->eip);
@@ -1167,7 +1166,7 @@ static void cursor(int sc)
                ctrl_alt_del();
                return;
        }
-       if (kbd_flag(KG_E0)) {
+       if (kbd_dead(KGD_E0)) {
                cur(sc);
                return;
        }
@@ -1226,7 +1225,7 @@ static void func(int sc)
 
 static void slash(int sc)
 {
-       if (!kbd_flag(KG_E0))
+       if (!kbd_dead(KGD_E0))
                do_self(sc);
        else if (vc_kbd_flag(kbd,VC_APPLIC))
                applkey('Q');
@@ -1244,7 +1243,7 @@ static void star(int sc)
 
 static void enter(int sc)
 {
-       if (kbd_flag(KG_E0) && vc_kbd_flag(kbd,VC_APPLIC))
+       if (kbd_dead(KGD_E0) && vc_kbd_flag(kbd,VC_APPLIC))
                applkey('M');
        else {
                put_queue(13);
@@ -1418,7 +1417,6 @@ static fptr key_table[] = {
 unsigned long kbd_init(unsigned long kmem_start)
 {
        int i;
-       unsigned char a;
        struct kbd_struct * kbd;
 
        kbd = kbd_table + 0;
@@ -1428,8 +1426,6 @@ unsigned long kbd_init(unsigned long kmem_start)
                kbd->kbd_flags = KBDFLAGS;
        }
        request_irq(KEYBOARD_IRQ,keyboard_interrupt);
-       a=inb_p(0x61);
-       outb_p(a|0x80,0x61);
-       outb_p(a,0x61);
+       keyboard_interrupt(0);
        return kmem_start;
 }
index 2eb51bfda3431bd39471791f6d75133995785c54..3dc5a2640d76096110019c443ca9936fd224b75d 100644 (file)
@@ -160,8 +160,9 @@ static void aux_interrupt(int cpl)
 static void release_aux(struct inode * inode, struct file * file)
 {
        poll_status();
-       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
        aux_write_dev(AUX_DISABLE_DEV);         /* disable aux device */
+       poll_status();
+       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
        aux_write_cmd(AUX_INTS_OFF);            /* disable controller ints */
        free_irq(AUX_IRQ);
        aux_busy = 0;
@@ -288,6 +289,9 @@ unsigned long psaux_init(unsigned long kmem_start)
        queue->head = queue->tail = 0;
        queue->proc_list = NULL;
        aux_present = 1;
+       poll_status();
+       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
+       aux_write_cmd(AUX_INTS_OFF);            /* disable controller ints */
        return kmem_start;
 }
 
index 46221e98a943695496e62548f17a2afd991bcb02..6b08ab028bb82d46b81461ab5a3f2878645e9e5c 100644 (file)
@@ -28,10 +28,8 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
        if (!tty->link)
                return;
        wake_up_interruptible(&tty->link->write_q.proc_list);
-       if (IS_A_PTY_MASTER(tty->line)) {
-               if (tty->link->session > 0)
-                       kill_sl(tty->link->session,SIGHUP,1);
-       }
+       if (IS_A_PTY_MASTER(tty->line))
+               tty_hangup(tty->link);
 }
 
 static inline void pty_copy(struct tty_struct * from, struct tty_struct * to)
index 5a4ac263eb4d68f605ceab3447fb1c4b47714299..8ce18ed745c620a8c503c43c12a58895005e4e3b 100644 (file)
@@ -59,7 +59,7 @@
  * 
  */
        
-#define NEW_INTERRUPT_ROUTINE
+#undef NEW_INTERRUPT_ROUTINE
        
 #define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
 
@@ -401,9 +401,8 @@ static void modem_status_intr(struct async_struct * info)
        unsigned char status = inb(UART_MSR + info->port);
 
        if (!(info->tty->termios->c_cflag & CLOCAL)) {
-               if (((status & (UART_MSR_DCD|UART_MSR_DDCD)) == UART_MSR_DDCD)
-                   && info->tty->session > 0)
-                       kill_sl(info->tty->session,SIGHUP,1);
+               if ((status & (UART_MSR_DCD|UART_MSR_DDCD)) == UART_MSR_DDCD)
+                       tty_hangup(info->tty);
 
                if (info->tty->termios->c_cflag & CRTSCTS)
                        info->tty->stopped = !(status & UART_MSR_CTS);
@@ -523,10 +522,8 @@ static void rs_timer(void)
                        if (!clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
                                wake_up_interruptible(&info->tty->write_q.proc_list);
                        }
-                       if (!clear_bit(RS_EVENT_HUP_PGRP, &info->event)) {
-                               if (info->tty->session > 0)
-                                       kill_sl(info->tty->session,SIGHUP,1);
-                       }
+                       if (!clear_bit(RS_EVENT_HUP_PGRP, &info->event))
+                               tty_hangup(info->tty);
                        if (!clear_bit(RS_EVENT_BREAK_INT, &info->event)) {
                                flush_input(info->tty);
                                flush_output(info->tty);
index 2e7b4c35a2b235ed48cb8d153d37a0de684f98dc..00e4952246e3b34548935a30efcf9ff19989d552 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/fcntl.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
+#include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/kd.h>
 #include <linux/mm.h>
@@ -54,6 +55,11 @@ struct tty_struct * redirect = NULL;
 struct wait_queue * keypress_wait = NULL;
 
 static int initialize_tty_struct(struct tty_struct *tty, int line);
+static int tty_read(struct inode *, struct file *, char *, int);
+static int tty_write(struct inode *, struct file *, char *, int);
+static int tty_select(struct inode *, struct file *, int, select_table *);
+static int tty_open(struct inode *, struct file *);
+static void tty_release(struct inode *, struct file *);
 
 void put_tty_queue(char c, struct tty_queue * queue)
 {
@@ -105,13 +111,228 @@ void tty_read_flush(struct tty_struct * tty)
                printk("tty_read_flush: bit already cleared\n");
 }
 
-void change_console(unsigned int new_console)
+static int hung_up_tty_read(struct inode * inode, struct file * file, char * buf, int count)
+{
+       return 0;
+}
+
+static int hung_up_tty_write(struct inode * inode, struct file * file, char * buf, int count)
+{
+       return -EIO;
+}
+
+static int hung_up_tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
+{
+       return 1;
+}
+
+static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+{
+       return -EBADF;
+}
+
+static struct file_operations tty_fops = {
+       tty_lseek,
+       tty_read,
+       tty_write,
+       NULL,           /* tty_readdir */
+       tty_select,
+       tty_ioctl,
+       NULL,           /* tty_mmap */
+       tty_open,
+       tty_release
+};
+
+static struct file_operations hung_up_tty_fops = {
+       tty_lseek,
+       hung_up_tty_read,
+       hung_up_tty_write,
+       NULL,           /* hung_up_tty_readdir */
+       hung_up_tty_select,
+       tty_ioctl,
+       NULL,           /* hung_up_tty_mmap */
+       tty_open,
+       tty_release
+};
+
+void tty_hangup(struct tty_struct * tty)
 {
-       if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
+       struct file * filp;
+       int dev;
+
+       if (!tty)
                return;
+       dev = 0x0400 + tty->line;
+       filp = file_table + NR_FILE;
+       while (filp-- > file_table) {
+               if (!filp->f_count)
+                       continue;
+               if (filp->f_rdev != dev)
+                       continue;
+               if (filp->f_op != &tty_fops)
+                       continue;
+               filp->f_op = &hung_up_tty_fops;
+       }
+       wake_up_interruptible(&tty->secondary.proc_list);
+       wake_up_interruptible(&tty->read_q.proc_list);
+       wake_up_interruptible(&tty->write_q.proc_list);
+       if (tty->session > 0)
+               kill_sl(tty->session,SIGHUP,1);
+}
+
+static inline int hung_up(struct file * filp)
+{
+       return filp->f_op == &hung_up_tty_fops;
+}
+
+extern int kill_proc(int pid, int sig, int priv);
+
+/*
+ * Performs the back end of a vt switch
+ */
+void complete_change_console(unsigned int new_console)
+{
+       unsigned char old_vc_mode;
+
        if (new_console == fg_console || new_console >= NR_CONSOLES)
                return;
+
+       /*
+        * If we're switching, we could be going from KD_GRAPHICS to
+        * KD_TEXT mode or vice versa, which means we need to blank or
+        * unblank the screen later.
+        */
+       old_vc_mode = vt_cons[fg_console].vc_mode;
        update_screen(new_console);
+
+       /*
+        * If this new console is under process control, send it a signal
+        * telling it that it has acquired. Also check if it has died and
+        * clean up (similar to logic employed in change_console())
+        */
+       if (vt_cons[new_console].vt_mode.mode == VT_PROCESS)
+       {
+               /*
+                * Send the signal as privileged - kill_proc() will
+                * tell us if the process has gone or something else
+                * is awry
+                */
+               if (kill_proc(vt_cons[new_console].vt_pid,
+                             vt_cons[new_console].vt_mode.acqsig,
+                             1) != 0)
+               {
+               /*
+                * The controlling process has died, so we revert back to
+                * normal operation. In this case, we'll also change back
+                * to KD_TEXT mode. I'm not sure if this is strictly correct
+                * but it saves the agony when the X server dies and the screen
+                * remains blanked due to KD_GRAPHICS! It would be nice to do
+                * this outside of VT_PROCESS but there is no single process
+                * to account for and tracking tty count may be undesirable.
+                */
+                       vt_cons[new_console].vc_mode = KD_TEXT;
+                       clr_vc_kbd_flag(kbd_table + new_console, VC_RAW);
+                       vt_cons[new_console].vt_mode.mode = VT_AUTO;
+                       vt_cons[new_console].vt_mode.waitv = 0;
+                       vt_cons[new_console].vt_mode.relsig = 0;
+                       vt_cons[new_console].vt_mode.acqsig = 0;
+                       vt_cons[new_console].vt_mode.frsig = 0;
+                       vt_cons[new_console].vt_pid = -1;
+                       vt_cons[new_console].vt_newvt = -1;
+               }
+       }
+
+       /*
+        * We do this here because the controlling process above may have
+        * gone, and so there is now a new vc_mode
+        */
+       if (old_vc_mode != vt_cons[new_console].vc_mode)
+       {
+               if (vt_cons[new_console].vc_mode == KD_TEXT)
+                       unblank_screen();
+               else
+               {
+                       timer_active &= ~(1<<BLANK_TIMER);
+                       blank_screen();
+               }
+       }
+
+       return;
+}
+
+/*
+ * Performs the front-end of a vt switch
+ */
+void change_console(unsigned int new_console)
+{
+       if (new_console == fg_console || new_console >= NR_CONSOLES)
+               return;
+
+       /*
+        * If this vt is in process mode, then we need to handshake with
+        * that process before switching. Essentially, we store where that
+        * vt wants to switch to and wait for it to tell us when it's done
+        * (via VT_RELDISP ioctl).
+        *
+        * We also check to see if the controlling process still exists.
+        * If it doesn't, we reset this vt to auto mode and continue.
+        * This is a cheap way to track process control. The worst thing
+        * that can happen is: we send a signal to a process, it dies, and
+        * the switch gets "lost" waiting for a response; hopefully, the
+        * user will try again, we'll detect the process is gone (unless
+        * the user waits just the right amount of time :-) and revert the
+        * vt to auto control.
+        */
+       if (vt_cons[fg_console].vt_mode.mode == VT_PROCESS)
+       {
+               /*
+                * Send the signal as privileged - kill_proc() will
+                * tell us if the process has gone or something else
+                * is awry
+                */
+               if (kill_proc(vt_cons[fg_console].vt_pid,
+                             vt_cons[fg_console].vt_mode.relsig,
+                             1) == 0)
+               {
+                       /*
+                        * It worked. Mark the vt to switch to and
+                        * return. The process needs to send us a
+                        * VT_RELDISP ioctl to complete the switch.
+                        */
+                       vt_cons[fg_console].vt_newvt = new_console;
+                       return;
+               }
+
+               /*
+                * The controlling process has died, so we revert back to
+                * normal operation. In this case, we'll also change back
+                * to KD_TEXT mode. I'm not sure if this is strictly correct
+                * but it saves the agony when the X server dies and the screen
+                * remains blanked due to KD_GRAPHICS! It would be nice to do
+                * this outside of VT_PROCESS but there is no single process
+                * to account for and tracking tty count may be undesirable.
+                */
+               vt_cons[fg_console].vc_mode = KD_TEXT;
+               clr_vc_kbd_flag(kbd_table + fg_console, VC_RAW);
+               vt_cons[fg_console].vt_mode.mode = VT_AUTO;
+               vt_cons[fg_console].vt_mode.waitv = 0;
+               vt_cons[fg_console].vt_mode.relsig = 0;
+               vt_cons[fg_console].vt_mode.acqsig = 0;
+               vt_cons[fg_console].vt_mode.frsig = 0;
+               vt_cons[fg_console].vt_pid = -1;
+               vt_cons[fg_console].vt_newvt = -1;
+               /*
+                * Fall through to normal (VT_AUTO) handling of the switch...
+                */
+       }
+
+       /*
+        * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
+        */
+       if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
+               return;
+
+       complete_change_console(new_console);
 }
 
 void wait_for_keypress(void)
@@ -272,14 +493,14 @@ int is_ignored(int sig)
 }
 
 static int available_canon_input(struct tty_struct *);
-static void __wait_for_canon_input(struct tty_struct *);
+static void __wait_for_canon_input(struct file * file, struct tty_struct *);
 
-static void wait_for_canon_input(struct tty_struct * tty)
+static void wait_for_canon_input(struct file * file, struct tty_struct * tty)
 {
        if (!available_canon_input(tty)) {
                if (current->signal & ~current->blocked)
                        return;
-               __wait_for_canon_input(tty);
+               __wait_for_canon_input(file, tty);
        }
 }
 
@@ -313,7 +534,7 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
                                return -EAGAIN;
                }
        } else if (L_CANON(tty)) {
-               wait_for_canon_input(tty);
+               wait_for_canon_input(file, tty);
                if (current->signal & ~current->blocked)
                        return -ERESTARTSYS;
        }
@@ -374,6 +595,8 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
                        TTY_WRITE_FLUSH(tty->link);
                if (!EMPTY(&tty->secondary))
                        continue;
+               if (hung_up(file))
+                       break;
                current->state = TASK_INTERRUPTIBLE;
                if (EMPTY(&tty->secondary))
                        schedule();
@@ -402,7 +625,7 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
        return 0;
 }
 
-static void __wait_for_canon_input(struct tty_struct * tty)
+static void __wait_for_canon_input(struct file * file, struct tty_struct * tty)
 {
        struct wait_queue wait = { current, NULL };
 
@@ -413,6 +636,8 @@ static void __wait_for_canon_input(struct tty_struct * tty)
                        break;
                if (current->signal & ~current->blocked)
                        break;
+               if (hung_up(file))
+                       break;
                schedule();
        }
        current->state = TASK_RUNNING;
@@ -447,6 +672,8 @@ static int write_chan(struct tty_struct * tty, struct file * file, char * buf, i
        while (nr>0) {
                if (current->signal & ~current->blocked)
                        break;
+               if (hung_up(file))
+                       break;
                if (tty->link && !tty->link->count) {
                        send_sig(SIGPIPE,current,0);
                        break;
@@ -524,25 +751,25 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
 
 static int tty_write(struct inode * inode, struct file * file, char * buf, int count)
 {
-       int dev,i;
+       int dev, i, is_console;
        struct tty_struct * tty;
 
        dev = file->f_rdev;
+       is_console = (inode->i_rdev == 0x0400);
        if (MAJOR(dev) != 4) {
                printk("tty_write: pseudo-major != 4\n");
                return -EINVAL;
        }
        dev = MINOR(dev);
-       if (redirect && ((dev == 0) || (dev == fg_console+1)))
+       if (is_console && redirect)
                tty = redirect;
        else
                tty = TTY_TABLE(dev);
        if (!tty || !tty->write)
                return -EIO;
-       if (MINOR(inode->i_rdev) &&
-           L_TOSTOP(tty) && (tty->pgrp > 0) &&
+       if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) &&
            (current->tty == dev) && (tty->pgrp != current->pgrp)) {
-               if (is_orphaned_pgrp(tty->pgrp))
+               if (is_orphaned_pgrp(current->pgrp))
                        return -EIO;
                if (!is_ignored(SIGTTOU)) {
                        (void) kill_pg(current->pgrp, SIGTTOU, 1);
@@ -555,11 +782,6 @@ static int tty_write(struct inode * inode, struct file * file, char * buf, int c
        return i;
 }
 
-static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
-{
-       return -EBADF;
-}
-
 /*
  * tty_open and tty_release keep up the tty count that contains the
  * number of opens done on a tty. We cannot use the inode-count, as
@@ -803,18 +1025,6 @@ static int tty_select(struct inode * inode, struct file * filp, int sel_type, se
        return 0;
 }
 
-static struct file_operations tty_fops = {
-       tty_lseek,
-       tty_read,
-       tty_write,
-       NULL,           /* tty_readdir */
-       tty_select,
-       tty_ioctl,
-       NULL,           /* tty_mmap */
-       tty_open,
-       tty_release
-};
-
 /*
  * This implements the "Secure Attention Key" ---  the idea is to
  * prevent trojan horses by killing all processes associated with this
@@ -920,9 +1130,9 @@ long tty_init(long kmem_start)
                tty_table[i] =  0;
                tty_termios[i] = 0;
        }
-       kmem_start = kbd_init(kmem_start);
        kmem_start = con_init(kmem_start);
        kmem_start = rs_init(kmem_start);
+       kmem_start = kbd_init(kmem_start);
        printk("%d virtual consoles\n\r",NR_CONSOLES);
        return kmem_start;
 }
index 02e720368f65993baae015422ccd092ba21f4d69..7021f2eade10654e4db559002b3cb671b02cf6e0 100644 (file)
@@ -386,16 +386,22 @@ int tty_ioctl(struct inode * inode, struct file * file,
                                        return -EINVAL;
                        }
                case TIOCCONS:
-                       if (!IS_A_PTY(dev))
-                               return -EINVAL;
+                       if (IS_A_CONSOLE(dev)) {
+                               if (!suser())
+                                       return -EPERM;
+                               redirect = NULL;
+                               return 0;
+                       }
                        if (redirect)
                                return -EBUSY;
                        if (!suser())
                                return -EPERM;
                        if (IS_A_PTY_MASTER(dev))
                                redirect = other_tty;
-                       else
+                       else if (IS_A_PTY_SLAVE(dev))
                                redirect = tty;
+                       else
+                               return -EINVAL;
                        return 0;
                case FIONBIO:
                        arg = get_fs_long((unsigned long *) arg);
index b3197343d5a9c72e10daac15d2d2d3f5ec8be242..5879b8e75d49dd0545819c6cb2cf49b5cb356e48 100644 (file)
 #include "vt_kern.h"
 
 /*
- * console (vt and kd) routines, as defined by usl svr4 manual
+ * Console (vt and kd) routines, as defined by USL SVR4 manual
+ *
+ * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
+ * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
+ * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
+ * always treat our set of vt as numbered 1..NR_CONSOLES (corresponding to
+ * ttys 0..NR_CONSOLES-1).
+ *
+ * Mostly done for X386, but with some slight differences and omissions.
+ * Should be useable by other SYSV programs in the future.
  */
 
 struct vt_cons vt_cons[NR_CONSOLES];
 
 extern int sys_ioperm(unsigned long from, unsigned long num, int on);
 extern void set_leds(void);
+extern void change_console(unsigned int new_console);
+extern void complete_change_console(unsigned int new_console);
 
 /*
  * these are the valid i/o ports we're allowed to change. they map all the
@@ -37,26 +48,53 @@ extern void set_leds(void);
 #define GPNUM (GPLAST - GPFIRST + 1)
 
 /*
- * turns on sound of some freq. 0 turns it off.
- * stolen from console.c, so i'm not sure if its the correct interpretation
+ * Generates sound of some count for some number of clock ticks
+ * [count = 1193180 / frequency]
+ *
+ * If freq is 0, will turn off sound, else will turn it on for that time.
+ * If msec is 0, will return immediately, else will sleep for msec time, then
+ * turn sound off.
+ *
+ * We use the BEEP_TIMER vector since we're using the same method to
+ * generate sound, and we'll overwrite any beep in progress. That may
+ * be something to fix later, if we like.
+ *
+ * We also return immediately, which is what was implied within the X
+ * comments - KDMKTONE doesn't put the process to sleep.
  */
-static int
-kiocsound(unsigned int freq)
+void
+kd_nosound(void)
 {
-       if (freq == 0) {
-               /* disable counter 2 */
-               outb(inb_p(0x61)&0xFC, 0x61);
-       }
-       else {
+       /* disable counter 2 */
+       outb(inb_p(0x61)&0xFC, 0x61);
+       return;
+}
+
+void
+kd_mksound(unsigned int count, unsigned int ticks)
+{
+       if (count)
+       {
                /* enable counter 2 */
                outb_p(inb_p(0x61)|3, 0x61);
                /* set command for counter 2, 2 byte write */
                outb_p(0xB6, 0x43);
                /* select desired HZ */
-               outb_p(freq & 0xff, 0x42);
-               outb((freq >> 8) & 0xff, 0x42);
+               outb_p(count & 0xff, 0x42);
+               outb((count >> 8) & 0xff, 0x42);
+
+               if (ticks)
+               {
+                       timer_table[BEEP_TIMER].expires = jiffies + ticks;
+                       timer_table[BEEP_TIMER].fn = kd_nosound;
+                       timer_active |= (1 << BEEP_TIMER);
+               }
        }
-       return 0;
+
+       else
+               kd_nosound();
+
+       return;
 }
 
 /*
@@ -66,7 +104,7 @@ kiocsound(unsigned int freq)
 int vt_ioctl(struct tty_struct *tty, struct file * file,
             unsigned int cmd, unsigned int arg)
 {
-       int console;
+       int console, i;
        unsigned char ucval;
        struct kbd_struct * kbd;
 
@@ -78,7 +116,22 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        kbd = kbd_table + console;
        switch (cmd) {
        case KIOCSOUND:
-               return kiocsound((unsigned int)arg);
+               kd_mksound((unsigned int)arg, 0);
+               return 0;
+
+       case KDMKTONE:
+       {
+               unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
+
+               /*
+                * Generate the tone for the appropriate number of ticks.
+                * If the time is zero, turn off sound ourselves.
+                */
+               kd_mksound(arg & 0xffff, ticks);
+               if (ticks == 0)
+                       kd_nosound();
+               return 0;
+       }
 
        case KDGKBTYPE:
                /*
@@ -120,21 +173,25 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                default:
                        return -EINVAL;
                }
-               if (vt_cons[console].vt_mode == (unsigned char) arg)
+               if (vt_cons[console].vc_mode == (unsigned char) arg)
                        return 0;
-               vt_cons[console].vt_mode = (unsigned char) arg;
+               vt_cons[console].vc_mode = (unsigned char) arg;
                if (console != fg_console)
                        return 0;
+               /*
+                * explicitly blank/unblank the screen if switching modes
+                */
                if (arg == KD_TEXT)
                        unblank_screen();
                else {
-                       timer_active &= 1<<BLANK_TIMER;
+                       timer_active &= ~(1<<BLANK_TIMER);
                        blank_screen();
                }
                return 0;
+
        case KDGETMODE:
                verify_area((void *) arg, sizeof(unsigned long));
-               put_fs_long(vt_cons[console].vt_mode, (unsigned long *) arg);
+               put_fs_long(vt_cons[console].vc_mode, (unsigned long *) arg);
                return 0;
 
        case KDMAPDISP:
@@ -155,6 +212,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        return -EINVAL;
                flush_input(tty);
                return 0;
+
        case KDGKBMODE:
                verify_area((void *) arg, sizeof(unsigned long));
                ucval = vc_kbd_flag(kbd, VC_RAW);
@@ -172,6 +230,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        ucval |= LED_CAP;
                put_fs_byte(ucval, (unsigned char *) arg);
                return 0;
+
        case KDSETLED:
                if (arg & ~7)
                        return -EINVAL;
@@ -190,6 +249,95 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                set_leds();
                return 0;
 
+       case VT_SETMODE:
+       {
+               struct vt_mode *vtmode = (struct vt_mode *)arg;
+               char mode;
+
+               verify_area((void *)vtmode, sizeof(struct vt_mode));
+               mode = get_fs_byte(&vtmode->mode);
+               if (mode != VT_AUTO && mode != VT_PROCESS)
+                       return -EINVAL;
+               vt_cons[console].vt_mode.mode = mode;
+               vt_cons[console].vt_mode.waitv = get_fs_byte(&vtmode->waitv);
+               vt_cons[console].vt_mode.relsig = get_fs_word(&vtmode->relsig);
+               vt_cons[console].vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
+               /* the frsig is ignored, so we set it to 0 */
+               vt_cons[console].vt_mode.frsig = 0;
+               vt_cons[console].vt_pid = current->pid;
+               vt_cons[console].vt_newvt = 0;
+               return 0;
+       }
+
+       case VT_GETMODE:
+       {
+               struct vt_mode *vtmode = (struct vt_mode *)arg;
+
+               verify_area((void *)arg, sizeof(struct vt_mode));
+               put_fs_byte(vt_cons[console].vt_mode.mode, &vtmode->mode);
+               put_fs_byte(vt_cons[console].vt_mode.waitv, &vtmode->waitv);
+               put_fs_word(vt_cons[console].vt_mode.relsig, &vtmode->relsig);
+               put_fs_word(vt_cons[console].vt_mode.acqsig, &vtmode->acqsig);
+               put_fs_word(vt_cons[console].vt_mode.frsig, &vtmode->frsig);
+               return 0;
+       }
+
+       /*
+        * Returns the first available (non-opened) console.
+        */
+       case VT_OPENQRY:
+               verify_area((void *) arg, sizeof(long));
+               for (i = 1; i <= NR_CONSOLES; ++i)
+                       if (!tty_table[i] || tty_table[i]->count == 0)
+                               break;
+               put_fs_long(i <= NR_CONSOLES ? i : -1, (unsigned long *)arg);
+               return 0;
+
+       /*
+        * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
+        * with num >= 1 (switches to vt 0, our console) are not allowed, just
+        * to preserve sanity.
+        */
+       case VT_ACTIVATE:
+               if (arg == 0 || arg > NR_CONSOLES)
+                       return -ENXIO;
+               change_console(arg - 1);
+               return 0;
+
+       /*
+        * If a vt is under process control, the kernel will not switch to it
+        * immediately, but postpone the operation until the process calls this
+        * ioctl, allowing the switch to complete.
+        *
+        * XXX Under X, the switching code calls VT_RELDISP with an arg of 2
+        * when it has switched back to it's vt. That's not kosher according
+        * to my documentation, which says this is only called when releasing
+        * the vt under your control.
+        */
+       case VT_RELDISP:
+               if (vt_cons[console].vt_mode.mode != VT_PROCESS ||
+                   vt_cons[console].vt_newvt < 0)
+                       return -EINVAL;
+
+               if (arg != 0)
+               {
+                       /*
+                        * If arg is nonzero, the current vt has been released,
+                        * so we can go ahead and complete the switch.
+                        */
+                       int newvt = vt_cons[console].vt_newvt;
+                       vt_cons[console].vt_newvt = -1;
+                       complete_change_console(newvt);
+               }
+               else
+               {
+                       /*
+                        * Mark that we've performed our part and return.
+                        */
+                       vt_cons[console].vt_newvt = -1;
+               }
+               return 0;
+
        default:
                return -EINVAL;
        }
index 5d72a3a3164f1c948c20f8f811af7a699b4a5e88..7df7f9fb79ea3725f089f5bdf983e4749b27a7c6 100644 (file)
@@ -5,11 +5,17 @@
  * this really is an extension of the vc_cons structure in console.c, but
  * with information needed by the vt package
  */
+
+#include <linux/vt.h>
+
 extern struct vt_cons {
-       int             vt_mode;                /* KD_TEXT, ... */
+       unsigned char   vc_mode;                /* KD_TEXT, ... */
        unsigned char   vc_kbdraw;
        unsigned char   vc_kbde0;
        unsigned char   vc_kbdleds;
+       struct vt_mode  vt_mode;
+       int             vt_pid;
+       int             vt_newvt;
 } vt_cons[NR_CONSOLES];
 
 #endif /* _VT_KERN_H */
index d7ff3cda7ea7d0119948d45909bc0861c0e86133..b5b8f2133d0821480c71498beba313e8e38967a0 100644 (file)
@@ -31,7 +31,6 @@ void verify_area(void * addr,int size)
        start = (unsigned long) addr;
        size += start & 0xfff;
        start &= 0xfffff000;
-       start += get_base(current->ldt[2]);
        while (size>0) {
                size -= 4096;
                write_verify(start);
@@ -39,31 +38,6 @@ void verify_area(void * addr,int size)
        }
 }
 
-int copy_mem(int nr,struct task_struct * p)
-{
-       unsigned long old_data_base,new_data_base,data_limit;
-       unsigned long old_code_base,new_code_base,code_limit;
-
-       code_limit = get_limit(0x0f);
-       data_limit = get_limit(0x17);
-       old_code_base = get_base(current->ldt[1]);
-       old_data_base = get_base(current->ldt[2]);
-       if (old_data_base != old_code_base) {
-               printk("ldt[0]: %08x %08x\n",current->ldt[0].a,current->ldt[0].b);
-               printk("ldt[1]: %08x %08x\n",current->ldt[1].a,current->ldt[1].b);
-               printk("ldt[2]: %08x %08x\n",current->ldt[2].a,current->ldt[2].b);
-               panic("We don't support separate I&D");
-       }
-       if (data_limit < code_limit)
-               panic("Bad data_limit");
-       new_data_base = old_data_base;
-       new_code_base = old_code_base;
-       p->start_code = new_code_base;
-       set_base(p->ldt[1],new_code_base);
-       set_base(p->ldt[2],new_data_base);
-       return copy_page_tables(p);
-}
-
 static int find_empty_process(void)
 {
        int i, task_nr;
@@ -163,7 +137,7 @@ int sys_fork(long ebx,long ecx,long edx,
        if (last_task_used_math == current)
                __asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
        p->kernel_stack_page = get_free_page(GFP_KERNEL);
-       if (!p->kernel_stack_page || copy_mem(nr,p)) {
+       if (!p->kernel_stack_page || copy_page_tables(p)) {
                task[nr] = NULL;
                REMOVE_LINKS(p);
                free_page(p->kernel_stack_page);
index c555f9f97ca14dcc87b22b231518aa448a45b5e0..7cc2a56416e557c125849033e354894eeb681f03 100644 (file)
@@ -64,7 +64,7 @@ int sys_syslog(int type, char * buf, int len)
                                sti();
                        }
                        i = 0;
-                       while (log_size && len) {
+                       while (log_size && i < len) {
                                c = *((char *) log_page+log_start);
                                log_start++;
                                log_size--;
index 52e0d41262560b41b7f081cebd7185d370939dc0..5b08cffcf8719bf2c3ceaac43e7631449cb2ed55 100644 (file)
@@ -229,6 +229,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
                current->flags |= PF_PTRACED;
                return 0;
        }
+       if (pid == 1)           /* you may not mess with init */
+               return -EPERM;
        if (!(child = get_task(pid)))
                return -ESRCH;
        if (request == PTRACE_ATTACH) {
index b59d8d8b2e0bd36cd3e9da22b7ab978b6072c42f..7b8672cd31a7079981a01cdece7281d65e7c3982 100644 (file)
@@ -14,6 +14,7 @@ SUBDIRS = tcp
 
 ifdef CONFIG_TCPIP
 NET_SUBDIRS = tcp
+TCP_ARCHIVE = tcp/tcpip.a
 endif
 
 .c.o:
@@ -26,7 +27,7 @@ endif
 OBJS   =  socket.o unix.o 
 
 net.o: $(OBJS) subdirs
-       $(LD) -r -o net.o $(OBJS) tcp/tcpip.o
+       $(LD) -r -o net.o $(OBJS) $(TCP_ARCHIVE)
 
 
 subdirs: dummy
@@ -40,8 +41,6 @@ dep:
        $(CPP) -M *.c > .depend
        @for i in $(SUBDIRS); do (cd $$i && echo $$i && $(MAKE) dep) || exit; done
 
-socket.o: Makefile
-
 dummy:
 
 #
index e87c045845963028f06811e6bcf6f2a97a8f6dff..85842ea2aa79654b43923d62e32932ad674d426f 100644 (file)
@@ -8,24 +8,25 @@ arp.o : arp.c /usr/include/linux/types.h /usr/include/linux/string.h /usr/includ
   /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
   /usr/include/linux/nfs_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
   /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
-  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/socket.h \
-  /usr/include/netinet/in.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h \
-  /usr/include/asm/system.h timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h \
-  eth.h tcp.h sock.h arp.h 
-dev.o : dev.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \
-  /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
-  /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
-  /usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h \
-  /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h \
-  /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
-  /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
-  /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/mm.h \
-  /usr/include/linux/signal.h /usr/include/linux/time.h /usr/include/linux/param.h \
-  /usr/include/linux/resource.h /usr/include/linux/vm86.h /usr/include/linux/math_emu.h \
-  /usr/include/linux/string.h /usr/include/linux/socket.h /usr/include/netinet/in.h \
-  /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h \
-  eth.h timer.h ip.h /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h \
-  /usr/include/linux/interrupt.h arp.h 
+  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/config.h \
+  /usr/include/linux/autoconf.h /usr/include/linux/socket.h /usr/include/netinet/in.h \
+  /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/sys/socket.h /usr/include/asm/system.h \
+  timer.h ip.h dev.h /usr/include/linux/sock_ioctl.h eth.h tcp.h sock.h arp.h 
+dev.o : dev.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/config.h \
+  /usr/include/linux/autoconf.h /usr/include/linux/types.h /usr/include/linux/kernel.h \
+  /usr/include/linux/sched.h /usr/include/linux/head.h /usr/include/linux/fs.h \
+  /usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
+  /usr/include/linux/vfs.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
+  /usr/include/linux/ext_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
+  /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/minix_fs_sb.h \
+  /usr/include/linux/ext_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
+  /usr/include/linux/nfs_fs_sb.h /usr/include/linux/mm.h /usr/include/linux/signal.h \
+  /usr/include/linux/time.h /usr/include/linux/param.h /usr/include/linux/resource.h \
+  /usr/include/linux/vm86.h /usr/include/linux/math_emu.h /usr/include/linux/string.h \
+  /usr/include/linux/socket.h /usr/include/netinet/in.h /usr/include/features.h \
+  /usr/include/sys/cdefs.h /usr/include/sys/socket.h dev.h eth.h timer.h ip.h \
+  /usr/include/linux/sock_ioctl.h tcp.h sock.h /usr/include/linux/errno.h /usr/include/linux/interrupt.h \
+  arp.h 
 eth.o : eth.c /usr/include/asm/segment.h /usr/include/asm/system.h /usr/include/linux/types.h \
   /usr/include/linux/kernel.h /usr/include/linux/sched.h /usr/include/linux/head.h \
   /usr/include/linux/fs.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
index b7695a355cfec199f95d4d880dec3cdc57c17e4c..faf3fdf7a7cb3bfbf5f15d33fe5be3fd6dcbd2b5 100644 (file)
@@ -19,8 +19,8 @@
 OBJS   = sock.o tcp.o ip.o timer.o we.o arp.o udp.o eth.o Space.o loopback.o \
          icmp.o protocols.o raw.o pack_type.o dev.o packet.o
 
-tcpip.o: $(OBJS)
-       $(LD) -r -o tcpip.o $(OBJS)
+tcpip.a: $(OBJS)
+       $(AR) rcs tcpip.a $(OBJS)
 
 subdirs: dummy
        for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
index 7ca42050d3c3387a5ee77091515c6e5d9a78c3a2..c824f74cb1d1c6bb382a934bd16bada73f30fa86 100644 (file)
@@ -73,19 +73,16 @@ static void
 send_arp_q(void)
 {
    struct sk_buff *skb;
-   struct sk_buff *skb2;
+   struct sk_buff *next;
 
    cli();
-   if (arp_q == NULL) return;
-
-   skb = arp_q;
-   do {
+   next = arp_q;
+   arp_q = NULL;
+   sti();
+   while ((skb = next) != NULL) {
      if (skb->magic != ARP_QUEUE_MAGIC)
        {
-        printk ("arp.c skb with bad magic - %X: squashing queue\n");
-        cli();
-        arp_q = NULL;
-        sti();
+        printk ("arp.c skb with bad magic - %X: squashing queue\n", skb->magic);
         return;
        }
      /* extra consistancy check. */
@@ -94,46 +91,54 @@ send_arp_q(void)
         || (unsigned long)(skb->next) > 16*1024*1024
 #endif
         )
-
        {
         printk ("dev.c: *** bug bad skb->next, squashing queue \n");
-        cli();
-        arp_q = NULL;
-        sti();
         return;
        }
 
+     /* first remove skb from the queue. */
+     next = skb->next;
+     if (next == skb)
+       {
+        next = NULL;
+       }
+     else
+       {
+        skb->prev->next = next;
+        next->prev = skb->prev;
+       }
+
      skb->magic = 0;
-     skb2=skb->next;
+     skb->next = NULL;
+     skb->prev = NULL;
 
-     sti();
      if (!skb->dev->rebuild_header (skb+1, skb->dev))
        {
-         cli();
-          if (skb->next == skb)
-            {
-               arp_q = NULL;
-            }
-          else
-            {
-               skb->next->prev = skb->prev;
-               skb->prev->next = skb->next;
-               arp_q = skb->next;
-            }
           skb->next = NULL;
           skb->prev = NULL;
           skb->arp  = 1;
-         sti();
           skb->dev->queue_xmit (skb, skb->dev, 0);
-
-         if (arp_q == NULL) break;
-
-          cli();
        }
-      skb=skb2;
-   } while (skb != arp_q);
-   sti();
-
+     else
+       {
+        cli();
+        skb->magic = ARP_QUEUE_MAGIC;      
+        if (arp_q == NULL)
+          {
+            skb->next = skb;
+            skb->prev = skb;
+            arp_q = skb;
+          }
+        else
+          {
+            skb->next = arp_q;
+            skb->prev = arp_q->prev;  
+            arp_q->prev->next = skb;
+            arp_q->prev = skb;
+          }
+        sti();
+       }
+   }
 }
 
 static  void
index 3351e037efa8dcdcf3f6eabcf21b19eabbd72e79..493cd9a6fc93a71ade00cca7a0ce632494e86ce9 100644 (file)
@@ -242,6 +242,12 @@ lock_skb (struct sk_buff *skb)
 void
 kfree_skb (struct sk_buff *skb, int rw)
 {
+  if (skb == NULL)
+    {
+      printk ("kfree_skb: skb = NULL\n");
+      return;
+    }
+
    if (skb->lock)
      {
        skb->free = 1;
@@ -300,7 +306,7 @@ get_new_socknum(struct proto *prot, unsigned short base)
   int best=0;
   int size=32767; /* a big num. */
   volatile struct sock *sk;
-  start++;
+
   if (base == 0) base = PROT_SOCK+1+(start % 1024);
   if (base <= PROT_SOCK)
     {
@@ -309,7 +315,7 @@ get_new_socknum(struct proto *prot, unsigned short base)
 
   /* now look through the entire array and try to find an empty
      ptr. */
-  for (i = 0; i < SOCK_ARRAY_SIZE; i++)
+  for (i=0; i < SOCK_ARRAY_SIZE; i++)
     {
       j = 0;
       sk = prot->sock_array[(i+base+1) & (SOCK_ARRAY_SIZE -1)];
@@ -318,7 +324,13 @@ get_new_socknum(struct proto *prot, unsigned short base)
          sk = sk->next;
          j++;
        }
-      if (j == 0) return (i+base+1);
+      if (j == 0)
+       {
+         start = (i+1+start )%1024;
+          PRINTK ("get_new_socknum returning %d, start = %d\n",
+                   i+base+1,start);
+         return (i+base+1);
+       }
       if (j < size) 
        {
          best = i;
@@ -330,6 +342,7 @@ get_new_socknum(struct proto *prot, unsigned short base)
     {
       best += SOCK_ARRAY_SIZE;
     }
+  PRINTK ("get_new_socknum returning %d, start = %d\n", best+base+1,start);
   return (best+base+1);
   
 }
@@ -445,12 +458,15 @@ destroy_sock(volatile struct sock *sk)
   /* just to be safe. */
   sk->inuse = 1;
 
+  /* incase it's sleeping somewhere. */
+  if (!sk->dead) wake_up (sk->sleep);
+
   remove_sock (sk);
   /* now we can no longer get new packets. */
 
   delete_timer((struct timer *)&sk->time_wait);
 
-  if (sk->send_tmp) kfree_skb (sk->send_tmp, FREE_WRITE);
+  if (sk->send_tmp != NULL) kfree_skb (sk->send_tmp, FREE_WRITE);
 
   /* cleanup up the write buffer. */
   for (skb = sk->wfront; skb != NULL; )
@@ -617,7 +633,7 @@ destroy_sock(volatile struct sock *sk)
 
   /* now if everything is gone we can free the socket structure, 
      otherwise we need to keep it around until everything is gone. */
-  if (sk->rmem_alloc <= 0 && sk->wmem_alloc <= 0)
+  if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0)
     {
        kfree_s ((void *)sk,sizeof (*sk));
     }
@@ -634,6 +650,8 @@ destroy_sock(volatile struct sock *sk)
        sk->timeout = TIME_DESTROY;
        reset_timer ((struct timer *)&sk->time_wait);
     }
+
+  PRINTK ("leaving destroy_sock\n");
   
 }
 
@@ -1004,10 +1022,9 @@ ip_proto_create (struct socket *sock, int protocol)
   /* how many packets we should send before forcing an ack. 
      if this is set to zero it is the same as sk->delay_acks = 0 */
 
-  sk->max_ack_backlog = MAX_ACK_BACKLOG;
+  sk->max_ack_backlog = 0;
   sk->inuse = 0;
-  sk->delay_acks = 1; /* default to waiting a while before sending
-                        acks.  */
+  sk->delay_acks = 0;
   sk->wback = NULL;
   sk->wfront = NULL;
   sk->rqueue = NULL;
@@ -1090,6 +1107,7 @@ ip_proto_release(struct socket *sock, struct socket *peer)
     }
   else
     {
+      PRINTK ("sk->linger set.\n");
        sk->prot->close(sk, 0);
        cli();
        while (sk->state != TCP_CLOSE)
@@ -1109,6 +1127,7 @@ ip_proto_release(struct socket *sock, struct socket *peer)
   /* this will destroy it. */
   release_sock (sk);
   sock->data = NULL;
+  PRINTK ("ip_proto_release returning\n");
   return (0);
 }
 
index 9d5d6812481ab1b435c91c2b6503c2699a8a3e87..c944d0dafa2dc658cb4b287e917ce5f30ecd94cc 100644 (file)
@@ -162,6 +162,8 @@ static  void
 tcp_time_wait (volatile struct sock *sk)
 {
    sk->state = TCP_TIME_WAIT;
+   sk->shutdown = SHUTDOWN_MASK;
+   if (!sk->dead) wake_up (sk->sleep);
    sk->time_wait.len = TCP_TIMEWAIT_LEN;
    sk->timeout = TIME_CLOSE;
    reset_timer ((struct timer *)&sk->time_wait);
@@ -219,11 +221,14 @@ tcp_err (int err, unsigned char *header, unsigned long daddr,
        return;
      }
 
+   printk ("tcp.c: icmp_err got error\n");
    sk->err = icmp_err_convert[err & 0xff].errno;
    if (icmp_err_convert[err & 0xff].fatal)
      {
        if (sk->state != TCP_ESTABLISHED)
-         sk->state = TCP_CLOSE;
+         {
+           sk->state = TCP_CLOSE;
+         }
        sk->prot->close(sk, 0);
      }
 
@@ -231,62 +236,105 @@ tcp_err (int err, unsigned char *header, unsigned long daddr,
    
 }
 
+static int
+tcp_readable (volatile struct sock *sk)
+{
+  unsigned long counted;
+  unsigned long amount;
+  struct sk_buff *skb;
+  int count=0;
+  int sum;
+
+  if (sk == NULL || sk->rqueue == NULL) return (0);
+
+  counted = sk->copied_seq;
+  amount = 0;
+  skb = sk->rqueue->next;
+
+  /* go until a push or until we are out of data.  */
+  do {
+    count ++;
+    if (count > 20)
+      {
+       printk ("tcp_readable, more than 20 packets without a psh\n");
+       printk ("possible read_queue corruption.\n");
+       return (amount);
+      }
+    if (before (counted+1, skb->h.th->seq)) break;
+    sum = skb->len - ( counted - skb->h.th->seq);
+    if (skb->h.th->syn) sum ++;
+    if (sum >= 0)
+      {
+       amount += sum;
+       if (skb->h.th->syn) amount --;
+       counted += sum;
+       if (skb->h.th->psh) break;
+      }
+    skb = skb->next;
+  } while (skb != sk->rqueue->next);
+  return (amount);
+}
+
+
 static int
 tcp_select (volatile struct sock *sk, int sel_type, select_table *wait)
 {
+  sk->inuse = 1;
   switch (sel_type)
     {
     case SEL_IN:
        select_wait (sk->sleep, wait);
-       if (sk->rqueue != NULL &&
-          (between (sk->copied_seq, sk->rqueue->next->h.th->seq - 1,
-                    sk->rqueue->next->h.th->seq + sk->rqueue->next->len) ||
-           sk->state == TCP_LISTEN))
+       if (sk->rqueue != NULL)
         {
-           return (1);
+          if (sk->state == TCP_LISTEN || tcp_readable(sk))
+            {
+              release_sock (sk);
+              return (1);
+            }
         }
 
-      switch (sk->state)
-       {
-       case TCP_LISTEN:
-       case TCP_ESTABLISHED:
-       case TCP_FIN_WAIT1:
-       case TCP_SYN_SENT:
-       case TCP_SYN_RECV:
-       case TCP_FIN_WAIT2:
-          return (0);
-       default:
+       if (sk->shutdown & RCV_SHUTDOWN)
+        {
+          release_sock (sk);
           return (1);
+        }
+       else
+        {
+          release_sock (sk);
+          return (0);
        }
 
     case SEL_OUT:
        select_wait (sk->sleep, wait);
 
-       switch(sk->state)
+       if (sk->shutdown & SEND_SHUTDOWN)
+        {
+          release_sock (sk);
+          return (0);
+        }
+       /* hack so it will probably be able to write something
+         if it says it's ok to write. */
+       if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
         {
-        default:
+          release_sock (sk);
           return (1);
+        }
+       release_sock (sk);
+       return (0);
 
-        case TCP_SYN_SENT:
-        case TCP_SYN_RECV:
-          return (0);
 
-        case TCP_ESTABLISHED:
-        case TCP_CLOSE_WAIT:
-          /* hack so it will probably be able to write something
-             if it says it's ok to write. */
-          if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) return (1);
-          return (0);
+     case SEL_EX:
+       select_wait(sk->sleep,wait);
+       if (sk->err)
+        {
+          release_sock (sk);
+          return (1);
         }
+       release_sock (sk);
+       return (0);
+     }
 
-    case SEL_EX:
-      select_wait(sk->sleep,wait);
-      if (sk->err) return (1);
-      if (sk->state == TCP_TIME_WAIT ||
-         sk->state == TCP_LAST_ACK)
-       return (1);
-      return (0);
-    }
+  release_sock (sk);
   return (0);
 }
 
@@ -303,32 +351,17 @@ tcp_ioctl (volatile struct sock *sk, int cmd, unsigned long arg)
 /*      case FIONREAD:*/
        {
          unsigned long amount;
-         unsigned long counted;
-         int sum;
-         struct sk_buff *skb;
 
          if (sk->state == TCP_LISTEN)
            return (-EINVAL);
 
-         counted = sk->copied_seq;
          amount = 0;
+         sk->inuse = 1;
          if (sk->rqueue != NULL)
            {
-             skb = sk->rqueue->next;
-             /* go until a push or until we are out of data.  */
-             do {
-               if (before (counted+1, skb->h.th->seq)) break;
-               sum = skb->len + skb->h.th->seq - counted;
-               if (sum > 0)
-                 {
-                   amount += sum;
-                   counted += sum;
-                 }
-               if (skb->h.th->psh) break;
-               skb = skb->next;
-               
-             } while (skb != sk->rqueue->next);
+             amount = tcp_readable(sk);
            }
+         release_sock (sk);
          PRINTK ("returning %d\n", amount);
          verify_area ((void *)arg, sizeof (unsigned long));
          put_fs_long (amount, (unsigned long *)arg);
@@ -340,12 +373,14 @@ tcp_ioctl (volatile struct sock *sk, int cmd, unsigned long arg)
          struct sk_buff *skb;
          int answ=0;
          /* try to figure out if we need to read some urgent data. */
+         sk->inuse = 1;
          if (sk->rqueue != NULL)
            {
              skb = sk->rqueue->next;
              if (sk->copied_seq+1 == skb->h.th->seq && skb->h.th->urg)
                answ = 1;
            }
+         release_sock (sk);
          verify_area ((void *) arg, sizeof (unsigned long));
          put_fs_long (answ, (void *) arg);
          return (0);
@@ -641,8 +676,8 @@ tcp_write (volatile struct sock *sk, unsigned char *from,
 
          if (nonblock)
            {
-             PRINTK ("tcp_write: return 2\n");
              release_sock (sk);
+             PRINTK ("tcp_write: return 2\n");
              if (copied) return (copied);
              return (-EAGAIN);
            }
@@ -655,7 +690,8 @@ tcp_write (volatile struct sock *sk, unsigned char *from,
             go to sleep. */
          release_sock (sk);
          cli();
-         if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
+         if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT &&
+             sk->err == 0)
            {
              interruptible_sleep_on (sk->sleep);
              if (current->signal & ~current->blocked)
@@ -752,7 +788,9 @@ tcp_write (volatile struct sock *sk, unsigned char *from,
 
          /* again we will try to avoid it. */
          cli ();
-         if (tmp <= sk->wmem_alloc)
+         if (tmp <= sk->wmem_alloc 
+             && (sk->state == TCP_ESTABLISHED || sk->state == TCP_CLOSE_WAIT )
+             && sk->err == 0)
            {
              interruptible_sleep_on (sk->sleep);
              if (current->signal & ~current->blocked)
@@ -971,18 +1009,26 @@ cleanup_rbuf (volatile struct sock *sk)
    /* at this point we should send an ack if the difference in
       the window, and the amount of space is bigger than
       TCP_WINDOW_DIFF */
-/*   PRINTK ("sk->window left = %d, sk->prot->rspace(sk)=%d\n",
-          sk->window - sk->bytes_rcv, sk->prot->rspace(sk));*/
+   PRINTK ("sk->window left = %d, sk->prot->rspace(sk)=%d\n",
+          sk->window - sk->bytes_rcv, sk->prot->rspace(sk));
 
    if ((sk->prot->rspace(sk) >
        (sk->window - sk->bytes_rcv + TCP_WINDOW_DIFF)))
      {
        sk->ack_backlog++;
-       /* force it to send an ack soon. */
-       if ( before (jiffies + TCP_ACK_TIME, sk->time_wait.when))
+       if (sk->ack_backlog > sk->max_ack_backlog)
         {
-          sk->time_wait.len = TCP_ACK_TIME;
-          reset_timer ((struct timer *)&sk->time_wait);
+          tcp_read_wakeup (sk);
+        }
+       else
+        {
+          /* force it to send an ack soon. */
+          if ( before (jiffies + TCP_ACK_TIME, sk->time_wait.when))
+            {
+              sk->time_wait.len = TCP_ACK_TIME;
+              sk->timeout = TIME_WRITE;
+              reset_timer ((struct timer *)&sk->time_wait);
+            }
         }
      }
 
@@ -1043,7 +1089,8 @@ tcp_read_urg(volatile struct sock * sk, int nonblock,
               /* now at this point, we may have gotten some data. */
               release_sock (sk);
               cli();
-              if (sk->urg == 0 || sk->rqueue == NULL)
+              if ((sk->urg == 0 || sk->rqueue == NULL) && sk->err == 0 
+                  && !(sk->shutdown & RCV_SHUTDOWN) )
                 {
                    interruptible_sleep_on (sk->sleep);
                    if (current->signal & ~current->blocked)
@@ -1085,8 +1132,8 @@ tcp_read_urg(volatile struct sock * sk, int nonblock,
 
 /* This routine copies from a sock struct into the user buffer. */
 static  int
-tcp_read(volatile struct sock *sk, unsigned char *to,
-        int len, int nonblock, unsigned flags)
+tcp_read (volatile struct sock *sk, unsigned char *to,
+         int len, int nonblock, unsigned flags)
 {
     int copied=0; /* will be used to say how much has been copied. */
     struct sk_buff *skb;
@@ -1102,15 +1149,6 @@ tcp_read(volatile struct sock *sk, unsigned char *to,
     /* this error should be checked. */
     if (sk->state == TCP_LISTEN) return (-ENOTCONN);
 
-    /* will catch some errors. */
-    if (sk->err)
-      {
-       int err;
-       err = -sk->err;
-       sk->err = 0;
-       return (err);
-      }
-
     /* urgent data needs to be handled specially. */
     if ((flags & MSG_OOB))
       return (tcp_read_urg (sk, nonblock, to, len, flags));
@@ -1184,10 +1222,17 @@ tcp_read(volatile struct sock *sk, unsigned char *to,
               PRINTK ("tcp_read about to sleep. state = %d\n",sk->state);
 
               release_sock (sk); /* now we may have some data waiting. */
+              /* or we could have changed state. */
               cli();
+              if ( sk->shutdown & RCV_SHUTDOWN || sk->err != 0)
+                {
+                  sk->inuse = 1;
+                  sti();
+                  continue;
+                }
 
                if ( sk->rqueue == NULL ||
-                   before (sk->copied_seq+1, sk->rqueue->next->h.th->seq))
+                   before (sk->copied_seq+1, sk->rqueue->next->h.th->seq) )
                  {
                     interruptible_sleep_on (sk->sleep);
                     if (current->signal & ~current->blocked)
@@ -1299,6 +1344,7 @@ tcp_shutdown (volatile struct sock *sk, int how)
  */
 
   if (!(how & SEND_SHUTDOWN)) return;
+  sk->inuse = 1;
 
   /* clear out any half completed packets. */
   if (sk->send_tmp)
@@ -1306,11 +1352,15 @@ tcp_shutdown (volatile struct sock *sk, int how)
 
   prot = (struct proto *)sk->prot;
   th=(struct tcp_header *)&sk->dummy_th;
-  buff=prot->wmalloc(sk, MAX_RESET_SIZE,1, GFP_KERNEL);
-  if (buff == NULL) return;
-
+  release_sock (sk); /* incase the malloc sleeps. */
+  buff=prot->wmalloc(sk, MAX_RESET_SIZE,1 , GFP_KERNEL);
+  if (buff == NULL) 
+    {
+      return;
+    }
   sk->inuse = 1;
 
+
   PRINTK("tcp_shutdown_send buff = %X\n", buff);
   buff->mem_addr = buff;
   buff->mem_len = MAX_RESET_SIZE;
@@ -1326,8 +1376,8 @@ tcp_shutdown (volatile struct sock *sk, int how)
   if (tmp < 0)
     {
       prot->wfree (sk,buff->mem_addr, buff->mem_len);
-      PRINTK ("Unable to build header for fin.\n");
       release_sock(sk);
+      PRINTK ("Unable to build header for fin.\n");
       return;
     }
 
@@ -1338,7 +1388,6 @@ tcp_shutdown (volatile struct sock *sk, int how)
   memcpy (t1, th, sizeof (*t1));
 
   t1->seq = net32(sk->send_seq);
-  sk->fin_seq = th->seq+1; /* Contains the one that needs to be acked */
 
   sk->send_seq++;
   buff->h.seq = sk->send_seq;
@@ -1683,8 +1732,9 @@ tcp_close (volatile struct sock *sk, int timeout)
   struct device *dev=NULL;
   int tmp;
   PRINTK ("tcp_close ((struct sock *)%X, %d)\n",sk, timeout);
+  print_sk (sk);
   sk->inuse = 1;
-  sk->keepopen = 0;
+  sk->keepopen = 1;
   sk->shutdown = SHUTDOWN_MASK;
 
   if (!sk->dead)
@@ -1700,10 +1750,13 @@ tcp_close (volatile struct sock *sk, int timeout)
        skb = sk->rqueue;
        do {
          skb2=skb->next;
+         /* if there is some real unread data, send a reset. */
+         if (skb->len > 0 &&
+             after (skb->h.th->seq + skb->len + 1, sk->copied_seq))
+           need_reset = 1;
          kfree_skb (skb, FREE_READ);
          skb=skb2;
        } while (skb != sk->rqueue);
-       need_reset = 1;
     }
   sk->rqueue = NULL;
 
@@ -1726,8 +1779,6 @@ tcp_close (volatile struct sock *sk, int timeout)
       if (timeout)
        tcp_time_wait(sk);
       release_sock (sk);
-      if (!need_reset)
-       return;
       break;
       
     case TCP_TIME_WAIT:
@@ -2117,14 +2168,18 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr)
   /* see if we are done. */
   if ( sk->state == TCP_TIME_WAIT)
     {
-       if (sk->rcv_ack_seq == sk->send_seq &&   
-          sk->acked_seq == sk->fin_seq);
        if (!sk->dead) wake_up (sk->sleep);
-       sk->state = TCP_CLOSE;
+       if (sk->rcv_ack_seq == sk->send_seq &&   
+          sk->acked_seq == sk->fin_seq)
+        {
+          sk->state = TCP_CLOSE;
+          sk->shutdown = SHUTDOWN_MASK;
+        }
     }
 
   if (sk->state == TCP_LAST_ACK || sk->state == TCP_FIN_WAIT2)
     {
+      if (!sk->dead) wake_up (sk->sleep);
       if (sk->rcv_ack_seq == sk->send_seq)
        {
           if (sk->acked_seq != sk->fin_seq)
@@ -2133,11 +2188,13 @@ tcp_ack (volatile struct sock *sk, struct tcp_header *th, unsigned long saddr)
             }
           else
             {
+              PRINTK ("tcp_ack closing socket - %X\n", sk);
+              print_sk (sk);
               tcp_send_ack (sk->send_seq, sk->acked_seq, sk, th, sk->daddr);
-               sk->state = TCP_CLOSE;
+              sk->shutdown = SHUTDOWN_MASK;
+              sk->state = TCP_CLOSE;
             }
        }
-      if (!sk->dead) wake_up (sk->sleep);
     }
 
   PRINTK ("leaving tcp_ack\n");
@@ -2176,17 +2233,16 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
 
   if (sk->shutdown & RCV_SHUTDOWN)
     {
-       /* just ack everything. */
        sk->acked_seq = th->seq + skb->len + th->syn + th->fin;
-       tcp_send_ack (sk->send_seq, sk->acked_seq, sk, skb->h.th, saddr);
+       tcp_reset (sk->saddr, sk->daddr, skb->h.th,
+                 sk->prot, NULL, skb->dev);
+       sk->state = TCP_CLOSE;
+       sk->err = EPIPE;
+       sk->shutdown = SHUTDOWN_MASK;
+       PRINTK ("tcp_data: closing socket - %X\n", sk);
+       print_sk (sk);
        kfree_skb (skb, FREE_READ);
-       if (sk->acked_seq == sk->fin_seq)
-        {
-           if (!sk->dead) wake_up (sk->sleep);
-           if (sk->state == TCP_TIME_WAIT || sk->state == TCP_LAST_ACK
-               || sk->state == TCP_FIN_WAIT2)
-             sk->state = TCP_CLOSE;
-        }
+       if (!sk->dead) wake_up (sk->sleep);
        return (0);
     }
 
@@ -2250,7 +2306,7 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
 
   if (before (sk->acked_seq, sk->copied_seq))
     {
-       PRINTK ("*** tcp.c:tcp_data bug acked < copied\n");
+       printk ("*** tcp.c:tcp_data bug acked < copied\n");
        sk->acked_seq = sk->copied_seq;
     }
 
@@ -2266,6 +2322,7 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
          /* when we ack the fin, we turn on the RCV_SHUTDOWN flag. */
          if (skb->h.th->fin)  
            {
+             if (!sk->dead) wake_up (sk->sleep);
              sk->shutdown |= RCV_SHUTDOWN;
            }
          
@@ -2281,6 +2338,7 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
                   if (skb2->h.th->fin)  
                     {
                       sk->shutdown |= RCV_SHUTDOWN;
+                      if (!sk->dead) wake_up (sk->sleep);
                     }
          
                    /* force an immediate ack. */
@@ -2308,6 +2366,7 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
               sk->time_wait.len = TCP_ACK_TIME;
               sk->timeout = TIME_WRITE;
               reset_timer ((struct timer *)&sk->time_wait);
+              sk->retransmits = 0;
            }
        }
    }
@@ -2327,10 +2386,15 @@ tcp_data (struct sk_buff *skb, volatile struct sock *sk,
        PRINTK ("data received on dead socket. \n");
     }
 
-  if (sk->state == TCP_FIN_WAIT2 && sk->acked_seq == sk->fin_seq)
+  if (sk->state == TCP_FIN_WAIT2 && sk->acked_seq == sk->fin_seq 
+      && sk->rcv_ack_seq == sk->send_seq)
     {
+      PRINTK ("tcp_data: entering last_ack state sk = %X\n", sk);
+      print_sk (sk);
       tcp_send_ack (sk->send_seq, sk->acked_seq, sk, th, saddr);
+      sk->shutdown = SHUTDOWN_MASK;
       sk->state = TCP_LAST_ACK;
+      if (!sk->dead) wake_up (sk->sleep);
     }
 
   return (0);
@@ -2384,19 +2448,21 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th,
       wake_up (sk->sleep);
     }
 
-  sk->err = 0;
   switch (sk->state)
     {
     case TCP_SYN_RECV:
     case TCP_SYN_SENT:
     case TCP_ESTABLISHED:
+      sk->fin_seq = th->seq+1; /* Contains the one that needs to be acked */
       sk->state = TCP_CLOSE_WAIT;
       break;
 
     case TCP_CLOSE_WAIT:
+    case TCP_FIN_WAIT2:
       break; /* we got a retransmit of the fin. */
 
     case TCP_FIN_WAIT1:
+      sk->fin_seq = th->seq+1; /* Contains the one that needs to be acked */
       sk->state = TCP_FIN_WAIT2;
       break;
 
@@ -2409,9 +2475,6 @@ tcp_fin (volatile struct sock *sk, struct tcp_header *th,
       reset_timer ((struct timer *)&sk->time_wait);
       return (0);
 
-    case TCP_FIN_WAIT2:
-      sk->state = TCP_CLOSE;
-      return (0);
     }
   /* there is no longer any reason to do this.  Just let tcp_data
      deal with it. */
@@ -2563,12 +2626,13 @@ tcp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
   memcpy_fromfs (&sin,usin, min(sizeof (sin), addr_len));
 
   if (sin.sin_family && sin.sin_family != AF_INET) return (-EAFNOSUPPORT);
-
+  sk->inuse = 1;
   sk->daddr = sin.sin_addr.s_addr;
   sk->send_seq = timer_seq*SEQ_TICK-seq_offset;
   sk->rcv_ack_seq = sk->send_seq -1;
   sk->err = 0;
   sk->dummy_th.dest = sin.sin_port;
+  release_sock (sk);
 
   buff=sk->prot->wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
   if (buff == NULL) 
@@ -2626,7 +2690,7 @@ tcp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
   
   sk->time_wait.len = TCP_CONNECT_TIME;
   reset_timer ((struct timer *)&sk->time_wait);
-  sk->retransmits = TCP_RETR1 - TCP_SYN_RETRIES;
+  sk->retransmits = TCP_RETR2 - TCP_SYN_RETRIES;
   release_sock (sk);
   return (0);
 }
@@ -2835,6 +2899,7 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        {
          sk->err = ECONNRESET;
          sk->state = TCP_CLOSE;
+         sk->shutdown = SHUTDOWN_MASK;
          if (!sk->dead)
            {
              wake_up (sk->sleep);
@@ -2859,20 +2924,34 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
 
       if (th->rst)
        {
+         /* this means the thing should really be closed. */
          sk->err = ECONNRESET;
-         sk->state = TCP_CLOSE;
-         if (!sk->dead)
+
+         if (sk->state == TCP_CLOSE_WAIT)
            {
-             wake_up (sk->sleep);
+             sk->err = EPIPE;
+           }
+
+         /* a reset with a fin just means that the
+            data was not all read. */
+         if (!th->fin)
+           {
+             sk->state = TCP_CLOSE;
+             sk->shutdown = SHUTDOWN_MASK;
+             if (!sk->dead)
+               {
+                 wake_up (sk->sleep);
+               }
+             kfree_skb (skb, FREE_READ);
+             release_sock(sk);
+             return (0);
            }
-         kfree_skb (skb, FREE_READ);
-         release_sock(sk);
-         return (0);
        }
       if (opt && (opt->security != 0 || opt->compartment != 0 || th->syn))
        {
           sk->err = ECONNRESET;
           sk->state = TCP_CLOSE;
+          sk->state = SHUTDOWN_MASK;
           tcp_reset (daddr, saddr,  th, sk->prot, opt,dev);
           if (!sk->dead)
             {
@@ -2902,6 +2981,13 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
            }
        }
 
+      if (th->fin && tcp_fin (sk, th, saddr, dev))
+       {
+         kfree_skb (skb, FREE_READ);
+         release_sock(sk);
+         return (0);
+       }
+
       if ( tcp_data (skb, sk, saddr, len))
        {
           kfree_skb (skb, FREE_READ);
@@ -2909,13 +2995,6 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
           return (0);
        }
 
-      if (!th->fin)
-       {
-         release_sock(sk);
-         return (0);
-       }
-
-      tcp_fin (sk, th, saddr, dev);
       release_sock(sk);
       return (0);
 
@@ -2989,8 +3068,9 @@ tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     case TCP_SYN_SENT:
       if (th->rst)
        {
-         sk->err = ECONNREFUSED;
+         sk->err = ECONNREFUSED ;
          sk->state = TCP_CLOSE;
+         sk->state = SHUTDOWN_MASK;
          if (!sk->dead)
            {
              wake_up (sk->sleep);
index 8401aea5c38e9a05eec4d59bbecb3443ec9ae755..f42807380e9acdfa185247b3a0c800f70c4cc131 100644 (file)
@@ -84,23 +84,23 @@ enum {
 #define MAX_RESET_SIZE 40 + sizeof (struct sk_buff) + MAX_HEADER
 #define MAX_WINDOW  12000
 #define MIN_WINDOW   2048
-#define MAX_ACK_BACKLOG 8
+#define MAX_ACK_BACKLOG 2
 #define MIN_WRITE_SPACE 2048
 #define TCP_WINDOW_DIFF 2048
 
-#define TCP_RETR1       7       /* this is howmany retries it does
+#define TCP_RETR1      10       /* this is howmany retries it does
                                   before it tries to figure out
                                   if the gateway is down. */
 
-#define TCP_RETR2      10      /* this should take between 3 and
-                                  ten minutes ( 1024 * rtt). */
+#define TCP_RETR2      25      /* this should take at least
+                                  90 minutes to time out. */
 
 
 #define TCP_TIMEOUT_LEN 720000 /* should be about 2 hrs. */
 #define TCP_TIMEWAIT_LEN 6000 /* How long to wait to sucessfully 
                                 close the socket, about 60 seconds. */
 #define TCP_ACK_TIME 35 /* time to delay before sending an ack. */
-#define TCP_DONE_TIME 2500 /* maximum time to wait before actually destroying
+#define TCP_DONE_TIME 250 /* maximum time to wait before actually destroying
                             a socket. */
 #define TCP_WRITE_TIME 100 /* initial time to wait for an ack,
                              after last transmit. */
index 37a829f7d902eac16085e45c47b45a724a241a84..080e9dc2defa369382d88d28e153ef5b3db93b87 100644 (file)
@@ -232,8 +232,18 @@ net_timer (void)
             break;
             
            case TIME_WRITE: /* try to retransmit. */
+            /* it could be we got here because we needed
+               to send an ack.  So we need to check for that. */
             if (sk->send_head != NULL)
               {
+                if (before (jiffies, sk->send_head->when + 2*sk->rtt))
+                  {
+                    sk->time_wait.len = 2*sk->rtt;
+                    sk->timeout = TIME_WRITE;
+                    reset_timer ((struct timer *)&sk->time_wait);
+                    release_sock (sk);
+                    break;
+                  }
                 PRINTK ("retransmitting.\n");
                 sk->prot->retransmit (sk, 0);
 
@@ -268,27 +278,6 @@ net_timer (void)
                  release_sock (sk);
                  break;
               }
-
-            /* if we have stuff which hasn't been written because the
-               window is too small, fall throught to TIME_KEEPOPEN */
-            if (sk->wfront == NULL && sk->send_tmp == NULL)
-              {
-                 release_sock (sk);
-                 break;
-              }
-
-            /* this basically assumes tcp here. */
-            /* exponential fall back. */
-            /* The rtt should quickly get back to normal once
-               we start sending packets again. */
-
-            sk->rtt *= 2;
-            sk->time_wait.len = sk->rtt;
-            sk->timeout = TIME_WRITE;
-            if (sk->prot->write_wakeup != NULL)
-              sk->prot->write_wakeup(sk);
-
-            reset_timer ((struct timer *)&sk->time_wait);
             release_sock (sk);
             break;
 
@@ -298,6 +287,12 @@ net_timer (void)
             if (sk->prot->write_wakeup != NULL)
               sk->prot->write_wakeup(sk);
             sk->retransmits ++;
+            if (sk->shutdown == SHUTDOWN_MASK)
+              {
+                sk->prot->close (sk,1);
+                sk->state = TCP_CLOSE;
+              }
+
             if (sk->retransmits > TCP_RETR1)
               {
                 PRINTK ("timer.c TIME_KEEPOPEN time-out 1\n");
index 1257542a15f49a1e52f874c7de7d46d2b3ecd019..ec2c4d597ca6263e36c4480803797877346bcf8e 100644 (file)
@@ -184,6 +184,26 @@ unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
        return (unix_proto_read (sock, buff, len, nonblock));
 }
 
+/*
+ * Since unix domain sockets use filenames to communicate, two sockets are
+ * the same if their strings are the same, even if their lengths are different
+ * (due to possible null terminations). Verified under SunOS 4.1.2
+ */
+static int
+same_path(char *s1, int l1, char *s2, int l2)
+{
+       /*
+        * Skip chars while they're equal
+        */
+       for (; l1 && l2 && *s1 == *s2; ++s1, ++s2, --l1, --l2);
+
+       /*
+        * Both must be exhausted, or one must be null terminated and the
+        * other either exhausted or null terminated, for the paths to be
+        * equivalent
+        */
+       return ((l1 == 0 || *s1 == '\0') && (l2 == 0 || *s2 == '\0'));
+}
 
 static struct unix_proto_data *
 unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
@@ -193,8 +213,10 @@ unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len)
        for (upd = unix_datas; upd <= last_unix_data; ++upd) {
                if (upd->refcnt && upd->socket &&
                    upd->socket->state == SS_UNCONNECTED &&
-                   upd->sockaddr_len == sockaddr_len &&
-                   memcmp(&upd->sockaddr_un, sockun, sockaddr_len) == 0)
+                   upd->sockaddr_un.sun_family == sockun->sun_family &&
+                   same_path(sockun->sun_path, sockaddr_len - UN_PATH_OFFSET,
+                             upd->sockaddr_un.sun_path,
+                             upd->sockaddr_len - UN_PATH_OFFSET))
                        return upd;
        }
        return NULL;
index 15e45b114e7c3c1d3d23868a2bad3f2fac13b5e6..dd045d4a883012c34b810a577db997d78a7043d9 100644 (file)
@@ -1,5 +1,5 @@
-#define UTS_RELEASE "0.99-44"
-#define UTS_VERSION "12/11/92"
-#define LINUX_COMPILE_TIME "23:05:18"
+#define UTS_RELEASE "0.99.pl1-46"
+#define UTS_VERSION "12/20/92"
+#define LINUX_COMPILE_TIME "14:31:20"
 #define LINUX_COMPILE_BY "root"
 #define LINUX_COMPILE_HOST "home"