Explicitly initialize on open instead of initializing via __constructor;
authorH. Peter Anvin <hpa@zytor.com>
Thu, 31 Aug 2006 18:35:15 +0000 (11:35 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 31 Aug 2006 18:35:15 +0000 (11:35 -0700)
more graceful handling of partial open/partial close.

com32/lib/sys/ansicon_write.c
com32/lib/sys/ansiserial_write.c
com32/lib/sys/close.c
com32/lib/sys/file.h
com32/lib/sys/open.c
com32/lib/sys/opendev.c
com32/lib/sys/rawcon_read.c
com32/lib/sys/serial_write.c
com32/lib/sys/stdcon_read.c
com32/lib/sys/stdcon_write.c
com32/lib/sys/vesacon_write.c

index 828a57e..89e6c4c 100644 (file)
@@ -100,33 +100,50 @@ static const char decvt_to_cp437[] =
   { 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361, 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304,
     0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 };
 
+/* Reference counter to the screen, to keep track of if we need reinitialization. */
+static int ansicon_counter = 0;
+
 /* Common setup */
-static void __constructor ansicon_init(void)
+int __ansicon_open(struct file_info *fp)
 {
   static com32sys_t ireg;      /* Auto-initalized to all zero */
   com32sys_t oreg;
 
-  /* Initial state */
-  memcpy(&st, &default_state, sizeof st);
-
-  /* Are we disabled? */
-  ireg.eax.w[0] = 0x000b;
-  __intcall(0x22, &ireg, &oreg);
+  (void)fp;
 
-  if ( (signed char)oreg.ebx.b[1] < 0 ) {
-    st.disabled = 1;
-    return;
+  if (!ansicon_counter) {
+    /* Initial state */
+    memcpy(&st, &default_state, sizeof st);
+    
+    /* Are we disabled? */
+    ireg.eax.w[0] = 0x000b;
+    __intcall(0x22, &ireg, &oreg);
+    
+    if ( (signed char)oreg.ebx.b[1] < 0 ) {
+      st.disabled = 1;
+    } else {
+      /* Force text mode */
+      ireg.eax.w[0] = 0x0005;
+      __intcall(0x22, &ireg, NULL);
+      
+      /* Get cursor shape */
+      ireg.eax.b[1] = 0x03;
+      ireg.ebx.b[1] = BIOS_PAGE;
+      __intcall(0x10, &ireg, &oreg);
+      st.cursor_type = oreg.ecx.w[0];
+    }
   }
 
-  /* Force text mode */
-  ireg.eax.w[0] = 0x0005;
-  __intcall(0x22, &ireg, NULL);
+  ansicon_counter++;
+  return 0;
+}
+
+int __ansicon_close(struct file_info *fp)
+{
+  (void)fp;
 
-  /* Get cursor shape */
-  ireg.eax.b[1] = 0x03;
-  ireg.ebx.b[1] = BIOS_PAGE;
-  __intcall(0x10, &ireg, &oreg);
-  st.cursor_type = oreg.ecx.w[0];
+  ansicon_counter--;
+  return 0;
 }
 
 /* Erase a region of the screen */
@@ -533,5 +550,6 @@ const struct output_dev dev_ansicon_w = {
   .flags      = __DEV_TTY | __DEV_OUTPUT,
   .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
   .write      = __ansicon_write,
-  .close      = NULL,
+  .close      = __ansicon_close,
+  .open       = __ansicon_open,
 };
index c7f4605..99301d5 100644 (file)
@@ -37,6 +37,8 @@
 #include <minmax.h>
 #include "file.h"
 
+extern int __ansicon_open(void);
+extern int __ansicon_close(struct file_info *);
 extern ssize_t __ansicon_write(struct file_info *, const void *, size_t);
 extern ssize_t __serial_write(struct file_info *, const void *, size_t);
 
@@ -51,5 +53,6 @@ const struct output_dev dev_ansiserial_w = {
   .flags      = __DEV_TTY | __DEV_OUTPUT,
   .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
   .write      = __ansiserial_write,
-  .close      = NULL,
+  .close      = __ansicon_close,
+  .open       = __ansicon_open,
 };
index f6a09cb..3bf6882 100644 (file)
@@ -49,6 +49,7 @@ int close(int fd)
     if ( rv )
       return rv;
   }
+  fp->iop = &dev_error_r;
 
   if ( fp->oop->close ) {
     rv = fp->oop->close(fp);
index 0161510..84ce7be 100644 (file)
@@ -58,13 +58,16 @@ struct input_dev {
   int fileflags;               /* Permitted file flags */
   ssize_t (*read)(struct file_info *, void *, size_t);
   int (*close)(struct file_info *);
+  int (*open)(struct file_info *);
 };
+
 struct output_dev {
   uint16_t dev_magic;          /* Magic number */
   uint16_t flags;              /* Flags */
   int fileflags;
   ssize_t (*write)(struct file_info *, const void *, size_t);
   int (*close)(struct file_info *);
+  int (*open)(struct file_info *);
 };
 
 /* File structure */
index cf23ee6..79fbc41 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2003-2004 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2003-2006 H. Peter Anvin - All Rights Reserved
  *
  *   Permission is hereby granted, free of charge, to any person
  *   obtaining a copy of this software and associated documentation
@@ -47,6 +47,7 @@ static const struct input_dev file_dev = {
   .fileflags = O_RDONLY,
   .read      = __file_read,
   .close     = __file_close,
+  .open      = NULL,
 };
 
 int open(const char *pathname, int flags, ...)
index 142baa1..5928b36 100644 (file)
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <com32.h>
 #include <string.h>
+#include <unistd.h>
 #include "file.h"
 
 /*
  * Open a special device
  */
 
-int opendev(const struct input_dev *idev, const struct output_dev *odev, int flags)
+int opendev(const struct input_dev *idev,
+           const struct output_dev *odev, int flags)
 {
   int fd;
   struct file_info *fp;
   int okflags;
+  int e;
 
   okflags = (idev ? idev->fileflags : 0) | (odev ? odev->fileflags : 0);
 
@@ -58,11 +61,31 @@ int opendev(const struct input_dev *idev, const struct output_dev *odev, int fla
     return -1;
   }
 
-  fp->iop         = idev ? idev : &dev_error_r;
-  fp->oop         = odev ? odev : &dev_error_w;
+  fp->iop         = &dev_error_r;
+  fp->oop         = &dev_error_w;
   fp->i.offset    = 0;
   fp->i.nbytes    = 0;
   fp->i.datap     = fp->i.buf;
 
+  if (idev) {
+    if (idev->open && (e = idev->open(fp))) {
+      errno = e;
+      goto puke;
+    }
+    fp->iop = idev;
+  }
+
+  if (odev) {
+    if (odev->open && (e = odev->open(fp))) {
+      errno = e;
+      goto puke;
+    }
+    fp->oop = odev;
+  }
+
   return fd;
+
+ puke:
+  close(fd);
+  return -1;
 }
index a0f1dcd..9058ac0 100644 (file)
@@ -76,4 +76,5 @@ const struct input_dev dev_rawcon_r = {
   .fileflags  = O_RDONLY,
   .read       = __rawcon_read,
   .close      = NULL,
+  .open       = NULL,
 };
index 45046bd..0235620 100644 (file)
@@ -63,4 +63,5 @@ const struct output_dev dev_serial_w = {
   .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
   .write      = __serial_write,
   .close      = NULL,
+  .open       = NULL,
 };
index 9eca2a8..12b2fa1 100644 (file)
@@ -73,4 +73,5 @@ const struct input_dev dev_stdcon_r = {
   .fileflags  = O_RDONLY,
   .read       = __stdcon_read,
   .close      = NULL,
+  .open       = NULL,
 };
index c528b43..61e039c 100644 (file)
@@ -67,4 +67,5 @@ const struct output_dev dev_stdcon_w = {
   .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
   .write      = __stdcon_write,
   .close      = NULL,
+  .open       = NULL,
 };
index bfd20db..2b0fb70 100644 (file)
@@ -100,7 +100,7 @@ static const char decvt_to_cp437[] =
     0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 };
 
 /* Common setup */
-static void __constructor vesacon_init(void)
+static void vesacon_init(void)
 {
   static com32sys_t ireg;      /* Auto-initalized to all zero */
   com32sys_t oreg;
@@ -533,4 +533,5 @@ const struct output_dev dev_vesacon_w = {
   .fileflags  = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
   .write      = __vesacon_write,
   .close      = NULL,
+  .init       = vesacon_init,
 };