diff -Nur dosemu-1.0.1/etc/global.conf dosemu-1.0.1-mauspatch/etc/global.conf
--- dosemu-1.0.1/etc/global.conf	Thu Sep 14 22:18:46 2000
+++ dosemu-1.0.1-mauspatch/etc/global.conf	Thu Sep 14 22:19:58 2000
@@ -176,7 +176,7 @@
   if ($_rdtsc) rdtsc on else rdtsc off endif
   pci $_pci
 
-  dosbanner on
+  dosbanner off
   timint $_timint
   mathco $_mathco
   if (strlen($_cpu))
@@ -536,6 +536,24 @@
 
     # misc stuff
     dpmi $_dpmi
+    if (strlen($_stime))
+      $xxx = (0)
+      if (strstr("time",$_stime))
+        $xxx = ($xxx+1)
+        if (strstr("user",$_stime))
+          $xxx = ($xxx+4)
+        endif
+      endif
+      if (strstr("date",$_stime))
+        $xxx = $(xxx+2)
+        if (strstr("user",$_stime))
+          $xxx = ($xxx+8)
+        endif
+      endif
+      stime ($xxx)
+    else
+      stime 9
+    endif
     if (strlen($_irqpassing))
       $yyy = "irqpassing { "
       foreach $xxx (" ", $_irqpassing)
diff -Nur dosemu-1.0.1/etc/global.conf.orig dosemu-1.0.1-mauspatch/etc/global.conf.orig
--- dosemu-1.0.1/etc/global.conf.orig	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/etc/global.conf.orig	Thu Sep 14 22:18:46 2000
@@ -0,0 +1,676 @@
+##############################################################################
+# This file is global.conf, it is _allways_ executed as part of the inititial
+# configuration.
+#
+# Linux dosemu  configuration  for parser versions >= 3 (dosemu-0.97.0.1)
+#
+# ./doc/README-tech.txt (chapter 2.) contains a description of the syntax
+# and the usage. However, you normal won't edit this file !!
+#
+# NOTES:
+#
+# 1. The file /etc/dosemu.conf (and optionally ~/.dosemurc) contains variable
+#    settings, that are included by /var/lib/dosemu/global.conf for doing the
+#    most reasonable configuration.
+#    The file /etc/dosemu.conf (and optionally ~/.dosemurc) is what gets
+#    updated by the menu driven 'setup-dosemu' tool.
+#
+# 2. We strongly recommend you to edit ONLY /etc/dosemu.conf.
+#    If you change /var/lib/dosemu/global.conf, you are at your own and
+#    could break 'setup-dosemu'. You really need to know a lot of DOSEMU
+#    internals before you fiddle with editing global.conf.
+#    However, some very special cases can only be handled in global.conf.
+#    
+# 3. The file global.conf (this one) must either
+#      - be in /var/lib/dosemu (the default, changeable via dosemu.users)
+#      - or given via -F option (from root login, else only on
+#        non-suid-root DOSEMU)
+#      - or be in $HOME/.dosemu/lib.
+#
+#    For the latter there must be given the following conditions:
+#      - in /etc/dosemu.user give the keyword 'private_setup' for this user
+#      - DOSEMU _must_ be non-suid-root, except for user root or if you
+#        give the keyword 'unrestricted' in addition to 'private_setup'.
+#
+# This file (global.conf) may also serve as an example file for
+#      .dosrc            ( old style user configuration file )
+#      option -I         ( configuration via commandline, see man/dos.1 )
+#
+# Access rights are defined in
+#
+#      /etc/dosemu.users
+#
+##############################################################################
+
+ifdef u_forceold
+  undef parser_version_3
+  define version_3_style_used
+endif
+
+ifndef parser_version_3
+  # normally won't come here, because older DOSEMUs don't use this file
+  # ... but if using -F option ...
+  include "/etc/dosemu.conf"
+else
+  # we are on version 3 parser
+
+  # for security reason we restrict the PATH and restore it later
+  # to its original value
+  $_DOSEMU_ORIG_PATH = $PATH
+  $PATH = "/usr/local/bin:/usr/bin:/bin"
+
+  ## we set some vital variable
+
+  if (!strlen($DOSEMU_LIB_DIR))
+    # be sure, because older DOSEMU won't set this
+    $DOSEMU_LIB_DIR = "/var/lib/dosemu";
+    $DOSEMU_CONF_DIR = "/etc";
+  endif
+
+  $CONFIG_VERSION = ( (0 << 24) | (97 << 16) | (2 << 8) | 0)
+  #                    ^           ^^           ^         ^
+  if ( $DOSEMU_VERSION_CODE < $CONFIG_VERSION )
+    abort "
+*** sorry, your ", $DOSEMU_LIB_DIR, "/global.conf doesn't match this dosemu version
+"
+  endif
+
+  $LIST_DELIM = " ,	"	#delimiters for lists <tab>, blank, comma
+
+
+  # we include the global settings from /etc/dosemu.conf
+  shell("test -f ", $DOSEMU_CONF_DIR, "/dosemu.conf")
+  if ( $DOSEMU_SHELL_RETURN)
+    abort "
+*** error: ", $DOSEMU_CONF_DIR, "/dosemu.conf not accessable
+    ... giving up.
+"
+  endif
+
+  undef version_3_style_used    # unset it to have a valid check below
+  $xxx = 'include "', $DOSEMU_CONF_DIR, '/dosemu.conf"';
+  $$xxx;
+  ifndef version_3_style_used
+    abort "
+*** Your ", $DOSEMU_CONF_DIR, "/dosemu.conf is obviously an old style or a too simple one.
+    Please read Quickstart and README.txt on how to upgrade.
+"
+  endif
+
+  ## we check if we have an ${HOME}/.dosemurc (given by $DOSEMU_RC),
+  ## if yes, we include it here 'under user scope', which means it has
+  ## all c_* classes undefined and can only change enviroment variables in
+  ## its own isolated name space (prefixed with 'dosemu_').
+  ## We later take over only such variables, that we allow.
+
+  $_dosemurc = $DOSEMU_RC         # we get that passed from 'parse_config()'
+  shell("test -f ", $_dosemurc)
+  if ( (!$DOSEMU_SHELL_RETURN) && ($DOSEMU_VERSION_CODE >= ( ((97 << 16) | (4 << 8) | 3))))
+    # we have a .dosemurc and can include
+    $_dosemurc = ' include "', $_dosemurc, '"';
+    enter_user_scope;
+    $$_dosemurc;
+    leave_user_scope;
+    define skip_dosrc;
+
+    ## now we take over the allowed variables, only those which exist
+    ## with 'dosemu_' prefixed will overwrite those without the prefix.
+
+    checkuservar $_debug,
+      $_features, $_mapping,
+      $_timint, $_mathco, $_cpu, $_pci, $_xms, $_ems, $_ems_frame,
+      $_emusys, $_emubat, $_emuini
+    checkuservar
+      $_term_char_set, $_term_color, $_term_updfreq, $_escchar, $_layout,
+      $_keybint
+    checkuservar
+      $_X_updfreq, $_X_title, $_X_icon_name, $_X_keycode, $_X_blinkrate,
+      $_X_font, $_X_mitshm, $_X_sharecmap, $_X_fixed_aspect, $_X_aspect_43,
+      $_X_lin_filt, $_X_bilin_filt, $_X_mode13fact, $_X_winsize, $_X_gamma,
+      $_X_vgaemu_memsize, $_X_lfb, $_X_pm_interface, $_X_mgrab_key, $_X_vesamode
+    ifdef guest
+      define restricted
+    else
+      checkuservar
+        $_speaker,
+        $_com1, $_com2, $_com3, $_com4, $_mouse, $_mouse_dev, $_mouse_flags, $_mouse_baud,
+        $_printer, $_printer_timeout, $_ports,
+        $_ipxsupport, $_novell_hack, $_vnet,
+        $_sound, $_sb_base, $_sb_irq, $_sb_dma, $_sb_dsp, $_sb_mixer, $_mpu_base
+    endif
+    ifndef restricted
+      checkuservar  $_hogthreshold, $_dpmi, $_vbootfloppy, $_aspi, $_ttylocks
+      $xxx = $_hdimage	# remember the contents for later check
+      checkuservar  $_hdimage
+      if ($xxx ne $_hdimage)
+        # the user changed it in .dosemurc, have to check
+        if (strlen($_hdimage) && ($DOSEMU_UID != $DOSEMU_EUID) )
+          # we are running suid-root as user, don't allow partition access
+          $yyy = $_hdimage
+          foreach $xxx ($LIST_DELIM, $yyy)
+            if (!strncmp($xxx, "/dev/", 4))
+              abort "
+*** sorry, your are not allowed to use ", $xxx, " in .dosemurc
+"
+            endif
+          done
+        endif
+      endif
+    endif
+  endif
+  ## end of .dosemurc inclusion
+
+  if ( $DOSEMU_VERSION_CODE >=  ( (99 << 16) | (13 << 8) | 2) )
+    if (strlen($_mapping))
+      mappingdriver $_mapping;
+    endif
+  endif
+
+  if (strlen($_debug))
+    debug $__debug ;
+  else
+    debug { off }
+  endif
+
+  if ($_cpuspeed) cpuspeed $_cpuspeed endif
+  if ($_rdtsc) rdtsc on else rdtsc off endif
+  pci $_pci
+
+  dosbanner on
+  timint $_timint
+  mathco $_mathco
+  if (strlen($_cpu))
+    $_cpu = "cpu ", $_cpu;
+    $$_cpu
+  else
+    cpu 80386
+  endif
+  xms $_xms
+  if ($_ems) ems { ems_size $_ems ems_frame $_ems_frame } else ems off endif
+  dosmem $_dosmem
+
+  if ($_emusys ne "") emusys $_emusys endif
+  if ($_emubat ne "") emubat $_emubat endif
+  if ($_emuini ne "") emuini $_emuini endif
+
+  $DISABLE_MOUSE = (0)
+  $DISABLE_SERIAL = (0)
+
+  ## terminal stuff, we check a lot to insure proper operation
+
+  $BEING_ON = ""
+  $USING_X = (0)
+  $REMOTE_HOST = ""
+
+  ## Note GNU sh-utils >= 2.0 changed the default behaviour such
+  #       that it doesn't display the peer for remote connections anymore.
+  #       We need -l option to get this. As GNU sh-utils 1.16 doesn't
+  #       have this option, we detect this case via shell return value.
+  $xxx = shell("who -l am i 2>/dev/null")
+  if ($DOSEMU_SHELL_RETURN)
+    # we have GNU sh-utils < 2.0
+    $xxx = shell("who am i")
+  endif
+  if ( ($DOSEMU_STDIN_IS_CONSOLE eq "1")
+                    || ( strlen($xxx) && (strchr($xxx, "(" ) < 0 )))
+    $BEING_ON = "console"
+  else
+    if (strstr($xxx, "(:") < 0)
+      $BEING_ON = "remote"
+      $REMOTE_HOST = strsplit($xxx, strchr($xxx,"(")+1,99)
+      $REMOTE_HOST = strdel($REMOTE_HOST, strchr($REMOTE_HOST,")"),99)
+    else
+      $BEING_ON = ""
+    endif
+    if ( (strchr($DOSEMU_OPTIONS,"X") >=0) && ($DISPLAY ne "") )
+      $USING_X = (1)
+    endif
+    if (strstr("xterm dtterm", $TERM) >= 0)
+      $BEING_ON = $BEING_ON, "_xterm"
+    else
+      if (strstr("linux console", $TERM) < 0)
+        # remote side must be some type of real terminal
+        $BEING_ON = $BEING_ON, "_terminal"
+      else
+        # remote side is a Linux console
+        $BEING_ON = $BEING_ON, "_console"
+      endif
+    endif
+  endif
+
+  warn "dosemu running on ", $BEING_ON;
+
+  $xxx = $_term_char_set
+  if ($xxx eq "")
+     $xxx = "latin"
+     if (strstr($BEING_ON, "_console") >= 0)
+       $xxx = "ibm"
+     endif
+  endif
+  if ( ($BEING_ON ne "console") && (!$USING_X) )
+    $DISABLE_MOUSE = (1)
+    if ($_term_color) $_term_color = "on" else $_term_color = "off" endif
+    terminal { charset $$xxx updatefreq $_term_updfreq  escchar $_escchar
+               color $$_term_color }
+  endif
+  if ( $DOSEMU_VERSION_CODE >= ( (97 << 16) | (10 << 8) | 5) )
+    charset $$xxx
+  endif
+
+  ## host checking. Naah, we won't let all in ;-)
+
+  ## first: logged in hosts
+  if (strlen($REMOTE_HOST) && strlen($_odd_hosts))
+    foreach $xxx ($LIST_DELIM,$_odd_hosts)
+      if ( ! strncmp($xxx, $REMOTE_HOST, strlen($REMOTE_HOST)))
+        abort "Sorry, your host is on the blacklist"
+      endif
+    done
+  endif
+  ## second: hosts on diskless machines, that aren't allowed
+  if (strlen($_diskless_hosts))
+    foreach $xxx ($LIST_DELIM, $_diskless_hosts)
+      if ( ! strncmp($xxx, $DOSEMU_HOST, strlen($DOSEMU_HOST)))
+        abort "Sorry, your host is on the blacklist"
+      endif
+    done
+  endif
+
+  ## X param settings
+
+  if ( $USING_X || (strchr($DOSEMU_OPTIONS,"L") >0) )
+    # running as xdos or DEXE (which may force X later)
+    if ($_X_keycode == -1) # we do not test for 'auto', because older
+                           # DOSEMU don't know it and we want older
+                           # versions also running with this global.conf
+      $_X_keycode = "keycode_auto"
+    else
+      if ($_X_keycode) $_X_keycode = "keycode" else $_X_keycode = "" endif
+    endif
+    if ($_X_sharecmap) $_X_sharecmap = "sharecmap" else $_X_sharecmap = "" endif
+    if ($_X_aspect_43) $_X_aspect_43 = "aspect_43" else $_X_aspect_43 = "" endif
+    if ($_X_lin_filt) $_X_lin_filt = "lin_filt" else $_X_lin_filt = "" endif
+    if ($_X_bilin_filt) $_X_bilin_filt = "bilin_filt" else $_X_bilin_filt = "" endif
+    if ($_X_mode13fact != 2)
+      $_X_mode13fact = "mode13fact ", $_X_mode13fact
+    else
+      $_X_mode13fact = ""
+    endif
+    $_X_gamma = "gamma ", (int($_X_gamma * 100))
+    if (strlen($_X_font)) $_X_font = 'font "', $_X_font, '"'; endif
+
+    if (strlen($_X_winsize))
+      $xxx = (strstr($_X_winsize,","))
+      $_X_winsize = "winsize (", strdel($_X_winsize,$xxx,999), ") , (",
+                    strsplit($_X_winsize,$xxx+1,999), ")"
+    endif
+
+    $xxx = $_X_vesamode
+    $_X_vesamode = ""
+    if (strlen($xxx))
+      foreach $yyy (" 	", $xxx)
+        $zzz = (strchr($yyy,","))
+        $_X_vesamode = "vesamode (", strdel($yyy,$zzz,999), "),(",
+                      strsplit($yyy,$zzz+1,999), ") "
+      done
+    endif
+    if (strlen($_X_mgrab_key))
+      $_X_mgrab_key = 'mgrab_key "', $_X_mgrab_key, '"'
+    endif
+    X { 
+      title $_X_title icon_name $_X_icon_name
+      updatefreq $_X_updfreq blinkrate $_X_blinkrate
+      fixed_aspect $_X_fixed_aspect vgaemu_memsize $_X_vgaemu_memsize
+      lfb $_X_lfb  pm_interface $_X_pm_interface mitshm $_X_mitshm
+      $$_X_keycode $$_X_sharecmap $$_X_aspect_43 $$_X_lin_filt $$_X_bilin_filt
+      $$_X_font $$_X_winsize $$_X_gamma
+      $$_X_vesamode $$_X_mode13fact $$_X_mgrab_key
+    };
+  endif
+
+  ifdef guest
+    ## /etc/dosemu.users defined 'guest' for this login
+    define restricted		# force restricted setting
+    $_hogthreshold = (1)	# force 'nice'
+    $_rawkeyboard = (off)	# force normal keyboard
+    if ($BEING_ON eq "console") video { vga } endif
+    sound_emu off
+    $DISABLE_MOUSE = (1)
+    $DISABLE_SERIAL = (1)
+  else
+    ## other then guest
+    # video settings
+    if ($BEING_ON eq "console")
+      if (!strlen($_video)) $_video = "plainvga" endif
+      if ($_console) $_console = "console" else $_console = "" endif
+      if ($_graphics)
+        $_graphics = "graphics"
+        $_console = "console"
+        $_vbios_seg = "vbios_seg ", ($_vbios_seg)
+        $_vbios_size = "vbios_size ", ($_vbios_size)
+        $_vmemsize = "memsize ", ($_vmemsize)
+        if ($_videoportaccess) allowvideoportaccess on endif
+      else
+        $_graphics = ""; $_vbios_seg = ""; $_vbios_size = ""; $_vmemsize = ""
+      endif
+      if (strlen($_chipset)) $_chipset = "chipset ",$_chipset endif
+      if ($_dualmon) $_dualmon = "dualmon" else $_dualmon = "" endif
+      video {
+        $$_video $$_console $$_graphics $$_chipset
+        $$_vbios_seg  $$_vbios_size $$_vmemsize $$_dualmon
+      }
+    else
+      if ($_dualmon) video {dualmon} endif
+    endif
+
+    ## sound settings
+    if ($_sound)
+      sound_emu { sb_base $_sb_base  sb_irq $_sb_irq  sb_dma $_sb_dma
+                  sb_mixer $_sb_mixer  mpu_base $_mpu_base }
+    else
+      sound_emu off
+    endif
+
+    ## serial
+    if ((!$DISABLE_SERIAL) && strlen($_ttylocks))
+      ttylocks { directory $_ttylocks }
+    endif
+    if ((!$DISABLE_SERIAL) && strlen($_com1))
+      if ($_mouse_dev eq "com1")
+        if (!$DISABLE_MOUSE) serial { mouse com 1 device $_com1 } endif
+        $_mouse = ""
+      else
+        if ($_com1 eq "virtual")
+          serial { com 1 virtual }
+        else
+          serial { com 1 device $_com1 }
+        endif
+      endif
+    endif
+    if ((!$DISABLE_SERIAL) && strlen($_com2))
+      if ($_mouse_dev eq "com2")
+        if (!$DISABLE_MOUSE) serial { mouse com 2 device $_com2 } endif
+        $_mouse = ""
+      else
+        if ($_com2 eq "virtual")
+          serial { com 2 virtual }
+        else
+          serial { com 2 device $_com2 }
+        endif
+      endif
+    endif
+    if ((!$DISABLE_SERIAL) && strlen($_com3))
+      if ($_mouse_dev eq "com3")
+        if (!$DISABLE_MOUSE) serial { mouse com 3 device $_com3 } endif
+        $_mouse = ""
+      else
+        if ($_com3 eq "virtual")
+          serial { com 3 virtual }
+        else
+          serial { com 3 device $_com3 }
+        endif
+      endif
+    endif
+    if ((!$DISABLE_SERIAL) && strlen($_com4))
+      if ($_mouse_dev eq "com4")
+        if (!$DISABLE_MOUSE) serial { mouse com 4 device $_com4 } endif
+        $_mouse = ""
+      else
+        if ($_com4 eq "virtual")
+          serial { com 4 virtual }
+        else
+          serial { com 4 device $_com4 }
+        endif
+      endif
+    endif
+
+
+    ## mouse settings
+    if ((!$DISABLE_MOUSE) && strlen($_mouse) && (strstr($_mouse_dev,"com")<0))
+      if ($_mouse_baud)
+        $_mouse_baud = "baudrate ", $_mouse_baud
+      else
+        $_mouse_baud = ""
+      endif
+      if (strlen($_mouse_dev))
+        $_mouse_dev = "device ", $_mouse_dev, " internaldriver"
+      endif
+      mouse { $$_mouse $$_mouse_dev $$_mouse_flags $$_mouse_baud }
+    endif
+
+  endif # end 'not guest'
+
+  hogthreshold $_hogthreshold
+
+  ## keyboard setting
+  if ($BEING_ON ne "console") $_rawkeyboard = (off) endif
+  if ($_layout eq "auto")
+    keyboard { layout auto keybint $_keybint  rawkeyboard $_rawkeyboard }
+  else
+    if ( strstr($_layout, "load") <0 )
+      # we use the builtin keytables
+      if (strlen($_layout)) $_layout = "layout ",$_layout
+      else $_layout = "layout us"  endif
+      keyboard {  $$_layout  keybint $_keybint  rawkeyboard $_rawkeyboard }
+    else
+      # we have to load a keytable
+      $yyy = ""
+      foreach $xxx ($LIST_DELIM, $_layout)
+        if ($xxx ne "load")
+          $yyy = $xxx
+        endif
+      done
+      if (!strlen($yyy))
+        abort "no keytable name in $_layout"
+      endif
+      shell("test -f ", $DOSEMU_LIB_DIR, "/keymap/", $yyy)
+      if ( $DOSEMU_SHELL_RETURN)
+        abort "keytable ",$yyy, "not found in ", $DOSEMU_LIB_DIR, "/keymap/*"
+      endif
+      $_layout = 'include "keymap/', $yyy, '"' ;
+      $$_layout
+      keyboard { keybint $_keybint  rawkeyboard $_rawkeyboard }
+    endif
+  endif
+
+  secure off
+  $_disks = ""
+  ifdef restricted
+    ## /etc/dosemu.users defined 'restricted' for this login
+    if (!strlen($_secure)) secure on endif
+    define c_normal
+    if (strchr($_secure,"d")>=0) dexe { secure } endif
+    ifdef guest
+      if (strchr($_secure,"g")>=0) secure on  endif
+    else
+      if (strchr($_secure,"n")>=0) secure on  endif
+      $_disks = $_hdimage_r
+    endif
+    if (strchr($_secure,"0")>=0) secure off endif
+    dpmi off
+    speaker emulated
+    ipxsupport off
+    # printer { options "%s"  command "lpr"  timeout 20 }
+  else
+    ## /etc/dosemu.users does allow full access for this login
+    dexe { allowdisk }
+    $_disks = $_hdimage
+    if (!strlen($_vbootfloppy))
+      bootC                      # default boot mode is 'from C:'
+    else
+      bootA                      # default boot mode is 'from A:'
+      $yyy = ""; $zzz = "";
+      foreach $xxx ($LIST_DELIM, $_vbootfloppy)
+        if (strlen($yyy))
+          $zzz = $xxx
+        else
+          $yyy = $xxx
+        endif
+      done
+      $_vbootfloppy = $DOSEMU_LIB_DIR, "/", $yyy
+      bootdisk { heads 2  sectors 18  tracks 80 threeinch  file $_vbootfloppy }
+      if (strlen($zzz))
+        $_disks = $_hdimage
+      endif
+    endif
+    if (strlen($_floppy_a))
+      $zzz = strsplit($_floppy_a, strstr($_floppy_a, ":"), 999);
+      if (strlen($zzz))
+        $zzz = strsplit($zzz, 1, 999)
+        $_floppy_a = strdel($_floppy_a, strstr($_floppy_a, ":"), 999);
+      else
+        $zzz = "/dev/fd0"
+      endif
+      floppy { device $$zzz $$_floppy_a }
+    endif
+    if (strlen($_floppy_b))
+      $zzz = strsplit($_floppy_b, strstr($_floppy_b, ":"), 999);
+      if (strlen($zzz))
+        $zzz = strsplit($zzz, 1, 999)
+        $_floppy_b = strdel($_floppy_b, strstr($_floppy_b, ":"), 999);
+      else
+        $zzz = "/dev/fd1"
+      endif
+      floppy { device $$zzz $$_floppy_b }
+    endif
+
+    # misc stuff
+    dpmi $_dpmi
+    if (strlen($_irqpassing))
+      $yyy = "irqpassing { "
+      foreach $xxx (" ", $_irqpassing)
+        $yyy = $yyy, "use_sigio ", $xxx
+      done
+      $yyy = $yyy, " }";
+      $$yyy
+    else
+      irqpassing off
+    endif
+    if (strlen($_hardware_ram))
+      hardware_ram { $$_hardware_ram }
+    endif
+    if (strlen($_speaker))
+      $_speaker = "speaker ", $_speaker;
+      $$_speaker
+    else
+      speaker off
+    endif
+    ipxsupport $_ipxsupport
+    if ($_novell_hack) pktdriver novell_hack  endif
+    vnet $_vnet
+    if (strlen($_printer))
+      foreach $xxx ($LIST_DELIM, $_printer)
+        $xxx = "'-P", $xxx, " %s'";
+        printer { options $$xxx  command "lpr"  timeout $_printer_timeout }
+      done
+    endif
+    if (strlen($_ports)) ports { $$_ports } endif
+  endif
+
+  ## setting up hdimages
+  $_mounted_devices = ""
+  if (strlen($_disks) && (!defined(c_dexerun)))
+    foreach $xxxx ($LIST_DELIM, $_disks)
+      $xxx_pref = ""
+      if ((strchr($xxxx, "*") + 1) && (strlen($xxxx) == strchr($xxxx, "*") + 1))
+        $xxx_pref = strdel($xxxx, strlen($xxxx) - 1, 1);
+        $xxxx = shell("cd '/var/lib/dosemu/", $xxx_pref, "' 2>/dev/null && echo -n *")
+        if ($DOSEMU_SHELL_RETURN)
+          $xxxx = strcat($xxx_pref, "*")
+          $xxx_pref = ""
+        endif
+      endif
+     foreach $xxx ($LIST_DELIM, $xxxx)
+      $xxx = strcat($xxx_pref, $xxx)
+      if (!strncmp($xxx, "/dev/", 4))
+        if (!strlen($_mounted_devices))
+            # we first get all mounted devices
+          $_mounted_devices = shell(" df | awk '/\dev\//{print $1}' | tr '\n' ' '");
+            # we try to get the swap device too
+          $_mounted_devices = $_mounted_devices, shell("awk '!/^\#/ && /\/dev/ && /swap/{print $1}' /etc/fstab | tr '\n' ' '");
+        endif
+        $yyy = strdel($xxx, strstr($xxx, ":ro"), 999);
+        $zzz = strsplit($xxx, strstr($xxx, ":ro"), 999);
+        $yyyy = strcat($yyy, ' ');
+        if (strstr($_mounted_devices, $yyyy) <0)
+            # device not in use
+          if (strlen($zzz))
+            disk { partition $yyy readonly };
+          else
+            disk { partition $yyy };
+          endif
+        else
+          abort "
+*** device ", $yyy, " in use, cannot do partition access
+"
+        endif
+      else
+        $yyy = strdel($xxx, strstr($xxx, ":ro"), 999);
+        $zzz = strsplit($xxx, strstr($xxx, ":ro"), 999);
+        $yyy = $DOSEMU_LIB_DIR, "/", $yyy
+        shell("test -d '", $yyy, "'")
+        if (!$DOSEMU_SHELL_RETURN)
+          if (strlen($zzz))
+            disk { directory $yyy readonly };
+          else
+            disk { directory $yyy };
+          endif
+        else
+          disk { image $yyy }
+        endif
+      endif
+     done
+    done
+  endif
+
+  ## setting up ASPI devices
+  ifndef restricted
+    if (strlen($_aspi))
+      foreach $xxx ($LIST_DELIM, $_aspi)
+        $zz = (1);
+        $yy2 = ""; $yy3 = (-1);
+        foreach $yyy (":", $xxx)
+          $zzz = "$yy", $zz, " = $yyy";
+          $zz = ($zz + 1);
+          $$zzz
+        done;
+        aspi { $yy1 devicetype $yy2 target $yy3 };
+      done
+    endif
+  endif
+
+  ## setting up the features list
+  if ( (  ($DOSEMU_VERSION_CODE >= ((98 << 16) | (3 << 8) | 3))
+             && ($DOSEMU_VERSION_CODE < (99 << 16)) )
+       || ($DOSEMU_VERSION_CODE > ((99 << 16) | (5 << 8))) )
+    if (strlen($_features))
+      foreach $xxx ($LIST_DELIM, $_features)
+        $yyy = strdel($xxx, strstr($xxx, ":"), 999);
+        $zzz = strsplit($xxx, strstr($xxx, ":"), 999);
+        if (strlen($zzz))
+          $zzz = strsplit($zzz, 1, 999);
+        else
+          $zzz = (0);
+        endif
+        feature { $yyy = $zzz };
+      done
+    endif
+  endif
+
+  # ... here we are and need disallow 'shell' any further
+  # so we can restore PATH
+  $PATH = $_DOSEMU_ORIG_PATH
+
+  ## define the allowed classes for subsequent .dosrc and -I parsing
+  ifdef restricted
+    undef c_all
+    ifdef guest
+      undef c_normal
+      define c_dexe
+      define c_nice
+      define c_x
+    endif
+  endif
+
+endif
+#############################################################################
diff -Nur dosemu-1.0.1/src/base/async/int.c dosemu-1.0.1-mauspatch/src/base/async/int.c
--- dosemu-1.0.1/src/base/async/int.c	Thu Sep 14 22:18:45 2000
+++ dosemu-1.0.1-mauspatch/src/base/async/int.c	Thu Sep 14 22:19:58 2000
@@ -36,6 +36,8 @@
 #include "priv.h"
 #include "doshelpers.h"
 
+#define UNIX_TIME
+
 #ifdef USING_NET
 #include "ipx.h"
 #endif
@@ -835,7 +837,11 @@
 static void int1a(u_char i)
 {
   time_t time_val;
+#ifdef UNIX_TIME
+  struct timeval tp;
+#else
   struct timeval;
+#endif
   struct timezone;
   struct tm *tm;
 
@@ -868,6 +874,28 @@
      * by the (realmode) INT8 handler should be always in sync.
      * Therefore, we keep INT1A,AH0 simple instead of trying to be too clever;-)
      */
+#ifdef UNIX_TIME
+    gettimeofday(&tp,NULL);
+    tm = localtime((time_t *) &tp.tv_sec);
+# if 0
+    test_date = tm->tm_year*10000+tm->tm_mon*100+tm->tm_mday;
+    if (check_date != test_date) {
+      start_time = akt_time;
+      check_date = tm->tm_year * 10000 + tm->tm_mon * 100 + tm->tm_mday;
+      g_printf("Over 24hrs forward or backward\n");
+      *(u_char *) (TICK_OVERFLOW_ADDR) += 0x1;
+    }
+# endif
+    ignore_segv++;
+    last_ticks = ((tm->tm_hour*60+tm->tm_min)*60+tm->tm_sec)*18.20648148;
+    last_ticks += tp.tv_usec*18.20648148/1000000;
+    *((unsigned long *)BIOS_TICK_ADDR) = last_ticks;
+    LO(ax) = *(u_char *) (TICK_OVERFLOW_ADDR) = 0;
+    LWORD(ecx) = (last_ticks >> 16) & 0xffff;
+    LWORD(edx) = last_ticks & 0xffff;
+    ignore_segv--;
+    set_ticks(last_ticks);
+#else
     {
       static int first = 1;
       if (first) {
@@ -883,7 +911,7 @@
     LWORD(ecx) = (last_ticks >> 16) & 0xffff;
     LWORD(edx) = last_ticks & 0xffff;
     *((u_char *)(TICK_OVERFLOW_ADDR)) = 0; /* clear the midnight flag */
-
+#endif
 #else /* not BIOSTIMER_ONLY_VIEW */
 
     /* pic_sys_time is a zero-based tick(1.19MHz) counter. As such, if we
@@ -977,6 +1005,26 @@
 SeeAlso: AH=00h,AH=03h,AH=04h,INT 21/AH=2Ch
 */
   case 2:			/* get time */
+#ifdef UNIX_TIME
+    time(&time_val);
+    tm = localtime((time_t *) &time_val);
+    g_printf("get time %d:%02d:%02dßn", tm->tm_hour,tm->tm_min,tm->tm_sec);
+#  if 0
+    gettimeofday(&tp, &tzp);
+    ticks = tp.tv_sec - (tzp.tz_minuteswest*60);
+#  endif
+    HI(cx) = tm->tm_hour % 10;
+    tm->tm_hour /= 10;
+    HI(cx) |= tm->tm_hour << 4;
+    LO(cx) = tm->tm_min % 10;
+    tm->tm_min /= 10;
+    LO(cx) |= tm->tm_min << 4;
+    HI(dx) = tm->tm_sec % 10;
+    tm->tm_sec /= 10;
+    HI(dx) |= tm->tm_sec << 4;
+    LO(dx) = 1;
+    NOCARRY;
+#else
     LOCK_CMOS;
     HI(cx) = BCD(GET_CMOS(CMOS_HOUR));
     LO(cx) = BCD(GET_CMOS(CMOS_MIN));
@@ -984,6 +1032,7 @@
     UNLOCK_CMOS;
     g_printf("INT1A: RTC time %02x:%02x:%02x\n",HI(cx),LO(cx),HI(dx));
     NOCARRY;
+#endif
     break;
 
 /*
@@ -1033,6 +1082,36 @@
 Note:	this function is also supported by the Sperry PC, which predates the
 	  IBM AT; the data is specified in binary rather than BCD on the
 	  Sperry, and the value of DL is ignored
+*/
+#ifdef UNIX_TIME
+  case 3:
+    if (config.int1a_allow_stime & 1) {
+      time(&time_val);
+      tm = localtime((time_t *) &time_val);
+      tm->tm_hour = ((HI(cx)>>4)&0xf)*10+(HI(cx)&0xf);
+      tm->tm_min  = ((LO(cx)>>4)&0xf)*10+(LO(cx)&0xf);
+      tm->tm_sec  = ((HI(dx)>>4)&0xf)*10+(HI(dx)&0xf);
+      tm->tm_isdst |= !!LO(dx); /* Anselm Kruis 9.4.96 */
+      if(-1 == (time_val=mktime(tm))) {
+        error("ERROR: timer: illegal time specified\n");
+        break;
+      }
+      if (config.int1a_allow_stime & 4) {
+        PRIV_SAVE_AREA
+        enter_priv_on();
+        DOS_SYSCALL(stime(&time_val));
+        leave_priv_setting();
+      } else
+        DOS_SYSCALL(stime(&time_val));
+      g_printf("WARNING: setting time: %s\n",asctime(tm));
+    } else
+      g_printf("ERROR: timer: can't set time\n");
+    break;
+#else
+    g_printf("INT1A: RTC: can't set time/date\n");
+    break;
+#endif
+/*
 --------B-1A05-------------------------------
 INT 1A - TIME - SET REAL-TIME CLOCK DATE (AT,XT286,PS)
 	AH = 05h
@@ -1042,11 +1121,37 @@
 	DL = day (BCD)
 Return: nothing
 */
-  case 3:			/* set time */
-  case 5:			/* set date */
-    g_printf("INT1A: RTC: can't set time/date\n");
+#ifdef UNIX_TIME
+  case 5:                       /* set time */
+    if(config.int1a_allow_stime & 2) {
+      time(&time_val);
+      tm = localtime((time_t *) &time_val);
+      tm->tm_mday = ((LO(dx)>>4)&0xf)*10+(LO(dx)&0xf);
+      tm->tm_mon  = ((HI(dx)>>4)&0xf)*10+(HI(dx)&0xf);
+      tm->tm_year = ( ((HI(cx)>>4)&0xf)*10+(HI(cx)&0xf) ) *100;
+      tm->tm_year +=((LO(cx)>>4)&0xf)*10+(LO(cx)&0xf);
+      tm->tm_year -= 1900;
+      tm->tm_mon--;
+      if(-1 == (time_val=mktime(tm))) {
+        error("ERROR: timer: illegal date specified\n");
+        break;
+      }
+      if (config.int1a_allow_stime & 8) {
+        PRIV_SAVE_AREA
+        enter_priv_on();
+        DOS_SYSCALL(stime(&time_val));
+        leave_priv_setting();
+      } else
+        DOS_SYSCALL(stime(&time_val));
+      g_printf("WARNING: setting time: %s\n",asctime(tm));
+    } else
+      g_printf("ERROR: timer: can't set time\n");
     break;
-
+#else
+     g_printf("INT1A: RTC: can't set time/date\n");
+     break;
+#endif
+          
   /* Notes: the alarm occurs every 24 hours until turned off, invoking INT 4A
   	each time the BIOS does not check for invalid values for the time, so
   	the CMOS clock chip's "don't care" setting (any values between C0h
diff -Nur dosemu-1.0.1/src/base/init/lexer.l dosemu-1.0.1-mauspatch/src/base/init/lexer.l
--- dosemu-1.0.1/src/base/init/lexer.l	Thu Sep 14 22:18:45 2000
+++ dosemu-1.0.1-mauspatch/src/base/init/lexer.l	Thu Sep 14 22:20:55 2000
@@ -376,6 +376,7 @@
 dosemumap               RETURN(DOSEMUMAP);
 logbufsize              RETURN(LOGBUFSIZE);
 logfilesize		RETURN(LOGFILESIZE);
+stime         RETURN(STIME);
 mappingdriver		RETURN(MAPPINGDRIVER);
 
 	/* sillyint values */
diff -Nur dosemu-1.0.1/src/base/init/lexer.l.orig dosemu-1.0.1-mauspatch/src/base/init/lexer.l.orig
--- dosemu-1.0.1/src/base/init/lexer.l.orig	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/src/base/init/lexer.l.orig	Thu Sep 14 22:18:45 2000
@@ -0,0 +1,1194 @@
+/* 
+ * (C) Copyright 1992, ..., 2000 the "DOSEMU-Development-Team".
+ *
+ * for details see file COPYING in the DOSEMU distribution
+ */
+
+%{
+
+#define YY_NO_UNPUT		1
+#define USE_LOOP_HANDLING	1
+
+#if USE_LOOP_HANDLING
+  #define YY_NEVER_INTERACTIVE 1 /* need this to avoid access to yyin within
+				    lexer code, even if yyin != NULL */
+  #define LOOP_LIMIT		1000 /* this to avoid infinite loops,
+  					if the user has errors in his
+  					config file */
+#endif
+
+#include <stdlib.h>
+#undef ECHO
+#include <termios.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <setjmp.h>
+#include <sys/stat.h>                    /* structure stat       */
+#include <unistd.h>                      /* prototype for stat() */
+
+#include "config.h"
+#include "emu.h"
+#include "cpu.h"
+#include "disks.h"
+#include "lpt.h"
+#include "video.h"
+#include "mouse.h"
+#include "serial.h"
+#include "timers.h"
+#include "keymaps.h"
+
+#include "parsglob.h"
+#include "parser.h"
+#include "lexer.h"
+int line_count;
+
+#define NESTING_DEPTH	32 /* as we handle loops as pseudo includes,
+			    * this defines the depth of nested loops
+			    * as well as that of includes
+			    */
+
+static int __active__=1, __next_ITEM_for_me__=0;
+#define __active_max (2*NESTING_DEPTH) /* Note: 'while' pushes twice */
+static int __active_stack[__active_max+1]={1,0};
+static int __active_i=1;
+int include_stack_ptr = 0;
+int last_include = 0;
+
+static void push__active();
+static void pop__active();
+static void enter_includefile(char * fname);
+static void enter_macrofile(char *variable);
+extern char *get_config_variable(char *name);
+extern int config_check_only;
+extern char *checked_getenv(const char *name);
+
+#if 0 /* this just to test the conditional code */
+  #define TESTACTIVE (({if(__active__)fprintf(stderr,">>>%s<<<\n", yytext);}),__active__)
+#else
+  #define TESTACTIVE __active__
+#endif
+
+#define RETURN if (TESTACTIVE) return
+#define MAY_BE  if (TESTACTIVE)
+
+#define MAY_BEFORME if (__next_ITEM_for_me__) { \
+  if (get_config_variable(yytext)) { \
+    __active__= (__next_ITEM_for_me__ > 0); \
+  } \
+  else __active__= (__next_ITEM_for_me__ < 0); \
+  __next_ITEM_for_me__=0; \
+} \
+else if (TESTACTIVE)
+
+#define MAY_BEINCLUDE(other_stuff) if (TESTACTIVE) { \
+  if (__next_ITEM_for_me__ == 2) { \
+    __next_ITEM_for_me__=0; \
+    yytext[strlen(yytext)-1] = '\0'; \
+    enter_includefile(&yytext[1]); \
+  } \
+  else other_stuff \
+}
+
+
+extern void yyerror(char* string, ...);
+extern void yywarn(char* string, ...);
+
+char *yy_vbuffer=0;
+
+#if USE_LOOP_HANDLING
+
+#define CACHEFILES_MAX  32
+#define MACROFILE	(CACHEFILES_MAX+1)
+
+#define YY_INPUT(buf,result,max_size) \
+  if (!yyin) { \
+    if (yy_vbuffer && yy_vbuffer[0]) { \
+      buf[(max_size)-1]=0; \
+      strncpy(buf,yy_vbuffer,max_size); \
+      if (buf[(max_size)-1]) { \
+        yy_vbuffer+=max_size; \
+        result=max_size; \
+      } \
+      else { \
+        result=strlen(buf); \
+        yy_vbuffer=0; \
+      } \
+    } \
+    else result=0; \
+  } \
+  else { \
+    if ( yy_current_buffer->yy_is_interactive ) { \
+      int c = getc( yyin ); \
+      result = c == EOF ? 0 : 1; \
+      buf[0] = (char) c; \
+    } \
+    else { \
+      if ((unsigned int)yyin <= CACHEFILES_MAX) { \
+        result = cachefile_read(buf, max_size, (unsigned int)yyin - 1 ); \
+      } \
+      else { \
+	if ((unsigned int)yyin == MACROFILE) { \
+	  result = macrofile_read(buf, max_size); \
+	} \
+        else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) && ferror( yyin ) ) \
+                  YY_FATAL_ERROR( "input in flex scanner failed" ); \
+      } \
+    } \
+  }
+
+/*
+ * We are intercepting the yylex() function calls from the parser
+ */ 
+#define OUR_YY_DECL int yylex YY_PROTO(( YYSTYPE* yylval ))
+OUR_YY_DECL;
+
+#undef YY_DECL
+#define YY_DECL static int real_yylex YY_PROTO(( YYSTYPE* yylval ))
+
+
+/*
+ * we intercept lexer before executing each action
+ */
+#define YY_USER_ACTION if (__loop_handling__ > 0) \
+			if (dump_input(yy_act)) break;
+
+static int __loop_handling__ = 0;
+static int dump_input(int rulenum);
+static void enter_cachefile(int cfile);
+static int cachefile_read(char *buf, int size, int cfile);
+static int chachefile_wrap(void);
+static int macrofile_read(char *buf, int size);
+static int macrofile_wrap(void);
+
+
+#else /* not USE_LOOP_HANDLING */
+
+
+#define YY_INPUT(buf,result,max_size) \
+  if (!yyin) { \
+    if (yy_vbuffer && yy_vbuffer[0]) { \
+      buf[(max_size)-1]=0; \
+      strncpy(buf,yy_vbuffer,max_size); \
+      if (buf[(max_size)-1]) { \
+        yy_vbuffer+=max_size; \
+        result=max_size; \
+      } \
+      else { \
+        result=strlen(buf); \
+        yy_vbuffer=0; \
+      } \
+    } \
+    else result=0; \
+  } \
+  else { \
+    if ( yy_current_buffer->yy_is_interactive ) { \
+      int c = getc( yyin ); \
+      result = c == EOF ? 0 : 1; \
+      buf[0] = (char) c; \
+    } \
+    else { \
+      if ( ((result = fread( buf, 1, max_size, yyin )) == 0) && ferror( yyin ) ) \
+                  YY_FATAL_ERROR( "input in flex scanner failed" ); \
+    } \
+  }
+
+#undef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( YYSTYPE* yylval ))
+
+#endif /* not USE_LOOP_HANDLING */
+
+
+%}
+
+DIGIT		[0-9]
+HEXDIGIT 	{DIGIT}|[a-fA-F]
+LETTER		[a-zA-Z]
+ALPHNUM		{LETTER}|{DIGIT}
+IDENT		_*{LETTER}({ALPHNUM}|_)*
+STRQUOTELESS	({LETTER}|[/\.\~])({ALPHNUM}|[_\~@\-\+:\./])*
+
+%%
+
+%{
+	/* NOTE: "include" _must_ be the first rule, we need to know
+	 *       the rule number, which _here_ is always '1'
+	 */
+#define INCLUDE_RULE_NUM	1
+#define LOOP_RULE_NUM		(INCLUDE_RULE_NUM+1)
+#define DONE_RULE_NUM		(LOOP_RULE_NUM+1)
+%}
+"include"		MAY_BE __next_ITEM_for_me__=2;
+"while"|"foreach"	MAY_BE {
+	#if USE_LOOP_HANDLING
+			  if (!__loop_handling__) {
+			    __loop_handling__ =1;
+			    YY_USER_ACTION
+			  }
+	#endif;
+			};
+"done"			if (__loop_handling__ <0) pop__active();
+"while__yy__"		{ push__active(); RETURN(WHILESTATEMENT); }
+"foreach__yy__"		{ push__active(); RETURN(FOREACHSTATEMENT); }
+
+	/* special characters */
+
+[{}()<>=,\-+\*;]		RETURN(yytext[0]);
+
+	/* conditionals */
+
+"if"			{ push__active(); RETURN(IFSTATEMENT); }
+"ifdef"			{ push__active(); if (__active__) __next_ITEM_for_me__=1; }
+"ifndef"		{ push__active(); if (__active__) __next_ITEM_for_me__=-1; }
+"else"			{ 
+			  if (__active__) __active__=0;
+			  else if (__active_stack[__active_i-1] ) __active__=1;
+			}
+"endif"			pop__active();
+
+	/* config variable settings */
+"define"		RETURN(DEFINE);
+"undef"			RETURN(UNDEF);
+"checkuservar"		RETURN(CHECKUSERVAR);
+"enter_user_scope"	MAY_BE {
+			  yylval->i_value = include_stack_ptr+1;
+			  return(ENTER_USER_SPACE);
+			}
+"leave_user_scope"	MAY_BE {
+			  yylval->i_value = include_stack_ptr+1;
+			  return(LEAVE_USER_SPACE);
+			}
+
+
+	/* boolean values */
+on			RETURN(L_ON);
+off			RETURN(L_OFF);
+auto			RETURN(L_AUTO);
+yes			RETURN(L_YES);
+no			RETURN(L_NO);
+
+	/* operators */
+"/"			RETURN('/');
+"div"			RETURN('/');
+"|"			RETURN(OR_OP);
+"^"			RETURN(XOR_OP);
+">>"			RETURN(SHR_OP);
+"<<"			RETURN(SHL_OP);
+"!"			RETURN(NOT_OP);
+"=="			RETURN(EQ_OP);
+">="			RETURN(GE_OP);
+"<="			RETURN(LE_OP);
+"!="			RETURN(NEQ_OP);
+"&&"			RETURN(L_AND_OP);
+"&"			RETURN(AND_OP);
+"||"			RETURN(L_OR_OP);
+"~"			RETURN(BIT_NOT_OP);
+"eq"			RETURN(STR_EQ_OP);
+"ne"			RETURN(STR_NEQ_OP);
+
+	/* numbers */
+{DIGIT}+		MAY_BE {yylval->i_value = atoi(yytext);
+				return(INTEGER); }
+
+0x{HEXDIGIT}+		MAY_BE {yylval->i_value = strtol(yytext, 0, 0);
+				return(INTEGER); }
+
+0b[01]+			MAY_BE {yylval->i_value = strtol(yytext+2, 0, 2);
+				return(INTEGER); }
+
+{DIGIT}+\.{DIGIT}*([eE]\-?{DIGIT}+)? MAY_BE {yylval->r_value = atof(yytext);
+				return(REAL); }
+
+	/* casts */
+"int"			RETURN(INTCAST);
+"real"			RETURN(REALCAST);
+
+	/* functions */
+"strlen"		RETURN(STRLEN);
+"strtol"		RETURN(STRTOL);
+"strncmp"		RETURN(STRNCMP);
+"strcat"		RETURN(STRCAT);
+"strpbrk"		RETURN(STRPBRK);
+"strsplit"		RETURN(STRSPLIT);
+"strdel"		RETURN(STRDEL);
+"strchr"		RETURN(STRCHR);
+"strrchr"		RETURN(STRRCHR);
+"strstr"		RETURN(STRSTR);
+"strspn"		RETURN(STRSPN);
+"strcspn"		RETURN(STRCSPN);
+"defined"		RETURN(DEFINED);
+"shell"			RETURN(SHELL);
+
+	/* just for test purposes */
+exprtest		RETURN(EXPRTEST);
+
+	/* keywords */
+
+feature			RETURN(FEATURE);
+abort			RETURN(ABORT);
+warn			RETURN(WARN);
+x			RETURN(L_X);
+dosbanner		RETURN(DOSBANNER);
+fastfloppy		RETURN(FASTFLOPPY);
+timint			RETURN(TIMINT);
+hogthreshold		RETURN(HOGTHRESH);
+speaker			RETURN(SPEAKER);
+ipxsupport		RETURN(IPXSUPPORT);
+pktdriver		RETURN(PKTDRIVER);
+debug			RETURN(DEBUG);
+mouse			RETURN(MOUSE);
+serial			RETURN(SERIAL);
+keyboard		RETURN(KEYBOARD);
+keystroke		RETURN(PRESTROKE);
+terminal		RETURN(TERMINAL);
+video			RETURN(VIDEO);
+allowvideoportaccess	RETURN(ALLOWVIDEOPORT);
+emuretrace		RETURN(EMURETRACE);
+mathco			RETURN(MATHCO);
+cpu			RETURN(CPU);
+cpuspeed		RETURN(CPUSPEED);
+rdtsc			RETURN(RDTSC);
+bootA			RETURN(BOOTA);
+bootC			RETURN(BOOTC);
+xms			RETURN(L_XMS);
+umb_max			RETURN(L_UMB);
+secure			RETURN(L_SECURE);
+ems			RETURN(L_EMS);
+dpmi			RETURN(L_DPMI);
+dosmem			RETURN(DOSMEM);
+ports			RETURN(PORTS);
+trace			RETURN(TRACE);
+clear			RETURN(CLEAR);
+sillyint		RETURN(SILLYINT);
+irqpassing		RETURN(SILLYINT);
+hardware_ram		RETURN(HARDWARE_RAM);
+disk			RETURN(DISK);
+bootdisk		RETURN(BOOTDISK);
+bootfile		RETURN(BOOTFILE);
+printer			RETURN(PRINTER);
+emusys                  RETURN(EMUSYS);
+emubat                  RETURN(EMUBAT);
+emuini                  RETURN(EMUINI);
+ttylocks		RETURN(TTYLOCKS);
+sound_emu               RETURN(L_SOUND);
+dosemumap               RETURN(DOSEMUMAP);
+logbufsize              RETURN(LOGBUFSIZE);
+logfilesize		RETURN(LOGFILESIZE);
+mappingdriver		RETURN(MAPPINGDRIVER);
+
+	/* sillyint values */
+use_sigio		RETURN(USE_SIGIO);
+
+	/* ems values */
+ems_size		RETURN(EMS_SIZE);
+ems_frame		RETURN(EMS_FRAME);
+
+	/* speaker values */
+
+emulated		RETURN(EMULATED);
+native			RETURN(NATIVE);
+
+	/* disk keywords */
+hdimage			RETURN(HDIMAGE);
+image			RETURN(HDIMAGE);
+partition		RETURN(L_PARTITION);
+wholedisk		RETURN(WHOLEDISK);
+readonly		RETURN(READONLY);
+threeinch		RETURN(THREEINCH);
+atapi			RETURN(ATAPI);
+fiveinch		RETURN(FIVEINCH);
+sectors			RETURN(SECTORS);
+cylinders		RETURN(CYLINDERS);
+tracks			RETURN(TRACKS);
+heads			RETURN(HEADS);
+offset			RETURN(OFFSET);
+floppy			RETURN(L_FLOPPY);
+cdrom			RETURN(CDROM);
+diskcyl4096		RETURN(DISKCYL4096);
+
+	/* keyboard */
+
+keytable		RETURN(KEYTABLE);
+layout			RETURN(LAYOUT);
+keybint			RETURN(KEYBINT);
+rawkeyboard		RETURN(RAWKEYBOARD);
+shift			RETURN(SHIFT);
+alt			RETURN(ALT);
+numpad			RETURN(NUMPAD);
+dump			RETURN(DUMP);
+		/* dead keys for accents in keytable */
+dgrave			RETURN(DGRAVE);
+dacute			RETURN(DACUTE);
+dcircum			RETURN(DCIRCUM);
+dtilde			RETURN(DTILDE);
+dbreve			RETURN(DBREVE);
+daboved			RETURN(DABOVED);
+ddiares			RETURN(DDIARES);
+dabover			RETURN(DABOVER);
+ddacute			RETURN(DDACUTE);
+dcedilla		RETURN(DCEDILLA);
+diota			RETURN(DIOTA);
+dogonek			RETURN(DOGONEK);
+dcaron			RETURN(DCARON);
+
+
+finnish			MAY_BE { yylval->i_value = KEYB_FINNISH;
+			  return(KEYB_LAYOUT); }
+finnish-latin1		MAY_BE { yylval->i_value = KEYB_FINNISH_LATIN1;
+			  return(KEYB_LAYOUT); }
+us			MAY_BE { yylval->i_value = KEYB_US; return(KEYB_LAYOUT); }
+uk			MAY_BE { yylval->i_value = KEYB_UK; return(KEYB_LAYOUT); }
+de			MAY_BE { yylval->i_value = KEYB_DE; return(KEYB_LAYOUT); }
+de-latin1		MAY_BE { yylval->i_value = KEYB_DE_LATIN1;
+			  return(KEYB_LAYOUT); }
+fr			MAY_BE { yylval->i_value = KEYB_FR; return(KEYB_LAYOUT); }
+fr-latin1		MAY_BE { yylval->i_value = KEYB_FR_LATIN1;
+			  return(KEYB_LAYOUT); }
+dk			MAY_BE { yylval->i_value = KEYB_DK; return(KEYB_LAYOUT); }
+dk-latin1		MAY_BE { yylval->i_value = KEYB_DK_LATIN1;
+			  return(KEYB_LAYOUT); }
+keyb-no			MAY_BE { yylval->i_value = KEYB_NO; return(KEYB_LAYOUT); }
+no-latin1		MAY_BE { yylval->i_value = KEYB_NO_LATIN1;
+			  return(KEYB_LAYOUT); }
+dvorak			MAY_BE { yylval->i_value = KEYB_DVORAK; return(KEYB_LAYOUT); }
+sg			MAY_BE { yylval->i_value = KEYB_SG; return(KEYB_LAYOUT); }
+sg-latin1		MAY_BE { yylval->i_value = KEYB_SG_LATIN1;
+			  return(KEYB_LAYOUT); }
+sf			MAY_BE { yylval->i_value = KEYB_SF; return(KEYB_LAYOUT); }
+sf-latin1		MAY_BE { yylval->i_value = KEYB_SF_LATIN1;
+			  return(KEYB_LAYOUT); }
+es			MAY_BE { yylval->i_value = KEYB_ES; return(KEYB_LAYOUT); }
+es-latin1		MAY_BE { yylval->i_value = KEYB_ES_LATIN1;
+			  return(KEYB_LAYOUT); }
+be			MAY_BE { yylval->i_value = KEYB_BE; return(KEYB_LAYOUT); }
+po			MAY_BE { yylval->i_value = KEYB_PO; return(KEYB_LAYOUT); }
+it			MAY_BE { yylval->i_value = KEYB_IT; return(KEYB_LAYOUT); }
+sw			MAY_BE { yylval->i_value = KEYB_SW; return(KEYB_LAYOUT); }
+hu			MAY_BE { yylval->i_value = KEYB_HU; return(KEYB_LAYOUT); }
+hu-cwi			MAY_BE { yylval->i_value = KEYB_HU_CWI; return(KEYB_LAYOUT); }
+hu-latin2		MAY_BE { yylval->i_value = KEYB_HU_LATIN2;
+			  return(KEYB_LAYOUT); }
+jp106			MAY_BE { yylval->i_value = KEYB_JP106; return(KEYB_LAYOUT); }
+pl			MAY_BE { yylval->i_value = KEYB_PL; return(KEYB_LAYOUT); }
+hr-cp852		MAY_BE { yylval->i_value = KEYB_HR_CP852;
+			  return(KEYB_LAYOUT); }
+cz-qwerty		MAY_BE { yylval->i_value = KEYB_CZ_QWERTY;
+			  return(KEYB_LAYOUT); }
+cz-qwertz		MAY_BE { yylval->i_value = KEYB_CZ_QWERTZ;
+			  return(KEYB_LAYOUT); }
+hr-latin2		MAY_BE { yylval->i_value = KEYB_HR_LATIN2;
+			  return(KEYB_LAYOUT); }
+keyb-user		MAY_BE { yylval->i_value = KEYB_USER; return(KEYB_LAYOUT); }
+
+	/* serial stuff */
+
+base			RETURN(BASE);
+irq			RETURN(IRQ);
+interrupt		RETURN(INTERRUPT);
+baudrate		RETURN(BAUDRATE);
+device			RETURN(DEVICE);
+com                     RETURN(COM);
+
+	/* lock file stuff */
+directory              RETURN(DIRECTORY);
+namestub               RETURN(NAMESTUB);
+binary                 RETURN(BINARY);
+
+	/* terminal stuff */
+
+charset			RETURN(CHARSET);
+updatefreq		RETURN(UPDATEFREQ);
+	/* updatelines		RETURN(UPDATELINES); */
+color			RETURN(COLOR);
+escchar			RETURN(ESCCHAR);
+	/* corner			RETURN(CORNER); */
+	/* method			RETURN(METHOD); */
+	/* normal			RETURN(NORMAL); */
+	/* xterm			RETURN(XTERM); */
+	/* fast			RETURN(FAST); */
+	/* ncurses			RETURN(NCURSES); */
+latin1			MAY_BE { yylval->i_value = CHARSET_LATIN1;
+			  return(CHARSET_TYPE); }
+latin2			MAY_BE { yylval->i_value = CHARSET_LATIN2;
+			  return(CHARSET_TYPE); }
+latin			MAY_BE { yylval->i_value = CHARSET_LATIN;
+			  return(CHARSET_TYPE); }
+ibm			MAY_BE { yylval->i_value = CHARSET_IBM;
+			  return(CHARSET_TYPE); }
+fullibm			MAY_BE { yylval->i_value = CHARSET_FULLIBM;
+			  return(CHARSET_TYPE); }
+
+	/* mouse types */
+
+microsoft		RETURN(MICROSOFT);
+ms3button		RETURN(MS3BUTTON);
+logitech		RETURN(LOGITECH);
+mmseries		RETURN(MMSERIES);
+mouseman		RETURN(MOUSEMAN);
+hitachi			RETURN(HITACHI);
+mousesystems		RETURN(MOUSESYSTEMS);
+busmouse		RETURN(BUSMOUSE);
+ps2			RETURN(PS2);
+internaldriver		RETURN(INTERNALDRIVER);
+emulate3buttons		RETURN(EMULATE3BUTTONS);
+cleardtr		RETURN(CLEARDTR);
+
+	/* video stuff - sorry for Matrox but MGA was already used */
+
+vga			RETURN(VGA);
+ega			RETURN(EGA);
+cga			RETURN(CGA);
+mga			RETURN(MGA);
+mda			RETURN(MGA);
+none			RETURN(NONE);
+console			RETURN(CONSOLE);
+graphics		RETURN(GRAPHICS);
+chipset			RETURN(CHIPSET);
+memsize			RETURN(MEMSIZE);
+fullrestore		RETURN(FULLREST);
+partialrestore		RETURN(PARTREST);
+vbios_file		RETURN(VBIOS_FILE);
+vbios_copy		RETURN(VBIOS_COPY);
+vbios_mmap		RETURN(VBIOS_MMAP);
+vbios_seg		RETURN(VBIOS_SEG);
+vbios_size		RETURN(VBIOS_SIZE_TOK);
+dualmon			RETURN(DUALMON);
+forcevtswitch		RETURN(FORCE_VT_SWITCH);
+pci			RETURN(PCI);
+plainvga		MAY_BE { yylval->i_value = PLAINVGA; return(CHIPSET_TYPE); }
+trident			MAY_BE { yylval->i_value = TRIDENT; return(CHIPSET_TYPE); }
+et4000			MAY_BE { yylval->i_value = ET4000; return(CHIPSET_TYPE); }
+diamond			MAY_BE { yylval->i_value = DIAMOND; return(CHIPSET_TYPE); }
+s3			MAY_BE { yylval->i_value = S3; return(CHIPSET_TYPE); }
+avance			MAY_BE { yylval->i_value = AVANCE; return(CHIPSET_TYPE); }
+ati			MAY_BE { yylval->i_value = ATI; return(CHIPSET_TYPE); }
+cirrus			MAY_BE { yylval->i_value = CIRRUS; return(CHIPSET_TYPE); }
+matrox			MAY_BE { yylval->i_value = MATROX; return(CHIPSET_TYPE); }
+wdvga			MAY_BE { yylval->i_value = WDVGA; return(CHIPSET_TYPE); }
+paradise		MAY_BE { yylval->i_value = WDVGA; return(CHIPSET_TYPE); }
+sis                     MAY_BE { yylval->i_value = SIS; return(CHIPSET_TYPE); }
+
+	/* xwindows stuff */
+
+display			RETURN(L_DISPLAY);
+title			RETURN(L_TITLE);
+icon_name		RETURN(ICON_NAME);
+keycode			RETURN(X_KEYCODE);
+keycode_auto		RETURN(X_KEYCODE_AUTO);
+blinkrate		RETURN(X_BLINKRATE);
+sharecmap		RETURN(X_SHARECMAP);
+mitshm                  RETURN(X_MITSHM);
+font			RETURN(X_FONT);
+fixed_aspect		RETURN(X_FIXED_ASPECT);
+aspect_43		RETURN(X_ASPECT_43);
+lin_filt		RETURN(X_LIN_FILT);
+bilin_filt		RETURN(X_BILIN_FILT);
+mode13fact		RETURN(X_MODE13FACT);
+winsize			RETURN(X_WINSIZE);
+gamma			RETURN(X_GAMMA);
+vgaemu_memsize		RETURN(VGAEMU_MEMSIZE);
+vesamode		RETURN(VESAMODE);
+lfb			RETURN(X_LFB);
+pm_interface		RETURN(X_PM_INTERFACE);
+mgrab_key		RETURN(X_MGRAB_KEY);
+
+        /* Sound stuff */
+
+sb_base                 RETURN(SB_BASE);
+sb_irq                  RETURN(SB_IRQ);
+sb_dma                  RETURN(SB_DMA);
+sb_dsp                  RETURN(SB_DSP);
+sb_mixer                RETURN(SB_MIXER);
+mpu_base                RETURN(MPU_BASE);
+
+	/* packet driver */
+novell_hack		RETURN(NOVELLHACK);
+	/* Vinod's dosnet stuff (when to use former libpacket.c.multi */
+vnet			RETURN(VNET);
+	/* debug flags */
+
+io			RETURN(IO);
+port			RETURN(PORT);
+config			RETURN(CONFIG);
+read			RETURN(READ);
+write			RETURN(WRITE);
+keyb			RETURN(KEYB);
+warning			RETURN(WARNING);
+general			RETURN(GENERAL);
+hardware		RETURN(HARDWARE);
+ipc			RETURN(L_IPC);
+network			RETURN(NETWORK);
+sound			RETURN(SOUND);
+
+	/* printer stuff */
+
+command			RETURN(COMMAND);
+timeout			RETURN(TIMEOUT);
+options			RETURN(OPTIONS);
+file			RETURN(L_FILE);
+
+	/* port/io stuff */
+
+ormask			RETURN(ORMASK);
+andmask			RETURN(ANDMASK);
+rdonly			RETURN(RDONLY);
+wronly			RETURN(WRONLY);
+rdwr			RETURN(RDWR);
+range			RETURN(RANGE);
+fast			RETURN(FAST);
+
+	/* dexe stuff */
+dexe			RETURN(DEXE);
+allowdisk		RETURN(ALLOWDISK);
+forcexdos		RETURN(FORCEXDOS);
+xdosonly		RETURN(XDOSONLY);
+
+	/* ASPI driver */
+aspi			RETURN(ASPI);
+devicetype		RETURN(DEVICETYPE);
+target			RETURN(TARGET);
+
+	/* strings */
+
+\'[^\']*\'		{
+			char *s;
+			for(s = strchr(yytext, '\n'); s != NULL; s = strchr(s+1,'\n'))
+			      line_count++;
+
+			MAY_BE { yytext[strlen(yytext)-1] = '\0';
+			  yylval->s_value = strdup(&yytext[1]);
+			  EXPRTYPE(yylval->s_value) = TYPE_STRING1;
+			  return(STRING); }
+			}
+
+{STRQUOTELESS}		MAY_BEFORME {
+			  yylval->s_value = strdup(yytext);
+			  EXPRTYPE(yylval->s_value) = TYPE_STRQUOTELESS;
+			  return(STRING); }
+${IDENT}		MAY_BE {
+				yylval->s_value = strdup(&yytext[1]);
+				EXPRTYPE(yylval->s_value) = TYPE_STRQUOTELESS;
+				return(VARIABLE);
+			}
+$${IDENT}		MAY_BE { enter_macrofile(&yytext[2]);}
+
+	/* Note: we need the rule numbers of below actions 
+	 *       The below first one is INCLUDEFILE_RULE_NUM
+	 */
+\"[^\"]*\"		{
+			char *s;
+			for(s = strchr(yytext, '\n'); s != NULL; s = strchr(s+1,'\n'))
+			      line_count++;
+
+			MAY_BEINCLUDE ( { yytext[strlen(yytext)-1] = '\0';
+			  yylval->s_value = strdup(&yytext[1]);
+			  EXPRTYPE(yylval->s_value) = TYPE_STRING;
+			  return(STRING); } )
+			}
+
+	/* comments & whitespace */
+
+[#][^\n]*\n		line_count++;   /* comments to (and including) EOLN */
+[ \t]+			;   		/* ignore all white space */
+\n			line_count++;	/* keep track of lines seen */
+.			;/* fprintf(stderr, "%s:%d discarding char '%c'\n", 
+				include_fnames[include_stack_ptr],line_count, yytext[0]); */
+
+
+%%
+	/* the above '\n' rule (last rule) has rule-number 'YY_NUM_RULES-1'
+	 * We have no other chance as to 'count' backward to get the
+	 * rule number of ' quoted string, comments, e.t.c'
+	 * BIG_FAT_NOTE: If you insert rules behind INCLUDEFILE_RULE_NUM,
+	 *               change INCLUDEFILE_RULE_NUM too !!!
+	 */
+#define INCLUDEFILE_RULE_NUM (YY_NUM_RULES-1 - 3)
+#define COMMENT_RULE_NUM (INCLUDEFILE_RULE_NUM +1)
+#define WHITESPACE_RULE_NUM (COMMENT_RULE_NUM +1)
+#define NEWLINE__RULE_NUM (WHITESPACE_RULE_NUM +1)
+
+#define MAX_INCLUDE_DEPTH NESTING_DEPTH
+static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH] ={0};
+char * include_fnames[MAX_INCLUDE_DEPTH] = {0};
+char * include_macbuf[MAX_INCLUDE_DEPTH] = {0};
+int include_lines[MAX_INCLUDE_DEPTH] = {0};
+
+static void enter_includefile(char * fname)
+{
+  PRIV_SAVE_AREA
+  FILE * new_yyin;
+  char fname_[256];
+  if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+    yyerror("Includes nested too deeply" );
+    return;
+  }
+  /* we want to have the include files in the same directory as
+   * the main config file, if we have no leading  '/'
+   * and we want "keymap/xxx" mapped to e.g. "/var/lib/dosemu/keymap/xxx"
+   */
+  if (fname[0] != '/') {
+    int i;
+    if (!strncmp(fname, KEYMAP_DIR, strlen(KEYMAP_DIR)))
+      strcpy(fname_, KEYMAP_LOAD_BASE_PATH);
+    else
+      strcpy(fname_, include_fnames[include_stack_ptr]);
+    i=strlen(fname_);
+    while (i && (fname_[i] != '/')) i--;
+    if (i) {
+      i++;
+      strcpy(fname_+i,fname);
+      fname=fname_;
+    }
+  }
+  if (get_config_variable("c_system")) enter_priv_on();
+  else enter_priv_off();
+  new_yyin = fopen( fname, "r" );
+  leave_priv_setting();
+  if ( ! new_yyin ) {
+    yyerror("cannot open includefile %s", fname);
+    return;
+  }
+  c_printf("CONF: opened include file %s\n", fname);
+  include_lines[include_stack_ptr] = line_count;
+  include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+  include_stack_ptr++;
+  include_fnames[include_stack_ptr] = strdup(fname);
+  line_count = 1;
+  yyin = new_yyin;
+  include_stack[include_stack_ptr] = yy_create_buffer( yyin, YY_BUF_SIZE );
+  yy_switch_to_buffer(include_stack[include_stack_ptr]);
+  last_include = 0;
+}
+
+
+#ifdef yywrap
+  error "yywrap defined elsewere, need our own one"
+#endif
+
+int yywrap(void)    /* this gets called at EOF of a parsed file */
+{
+  if (include_stack_ptr <= 0 ) return(1);
+#if USE_LOOP_HANDLING
+#if 1
+  if ((unsigned int)yyin <= CACHEFILES_MAX) return chachefile_wrap();
+  if ((unsigned int)yyin == MACROFILE) return macrofile_wrap();
+#else
+  if (macrobuffer) return macrofile_wrap();
+  if (__loop_handling__ < 0) return chachefile_wrap();
+#endif
+#endif
+  yy_switch_to_buffer(include_stack[include_stack_ptr-1] );
+  fclose(include_stack[include_stack_ptr]->yy_input_file);
+  yy_delete_buffer(include_stack[include_stack_ptr]);
+  c_printf("CONF: closed include file %s\n", include_fnames[include_stack_ptr]);
+  free(include_fnames[include_stack_ptr]);
+  include_stack_ptr--;
+  line_count=include_lines[include_stack_ptr];
+  last_include = 0;
+  return(0);
+}
+
+
+extern void yyerror(char* string, ...);
+
+static void push__active()
+{
+  if (config_check_only>2)
+    fprintf(stderr, "PUSH %d->%d %d >%s<\n", __active_i, __active_i+1, __active__, yytext);
+  __active_stack[__active_i++]=__active__;
+  if (__active_i > __active_max) {
+    __active_i = __active_max;
+    yyerror("Lexer block stack overflow, unmatching  if..else..endif");
+  }
+}
+
+static void pop__active()
+{
+  if (config_check_only>2)
+    fprintf(stderr, "POP %d<-%d %d >%s< %d\n", __active_i-1, __active_i, __active__, yytext, __loop_handling__);
+  if (__active_i <=0) {
+    yyerror("Lexer block stack underflow, unmatching  if..else..endif");
+    return;
+  }
+  __active__=__active_stack[--__active_i];
+}
+
+void tell_lexer_if(int value)
+{
+  __active__ = value !=0;
+}
+
+
+#if USE_LOOP_HANDLING
+
+/* ---------------------------------------------------------
+ * yylex() wrapper
+ *
+ * Here the record/replay stuff is handled.
+ * We need that in order to realize 'while' loops or such things
+ */
+
+
+#define SAVEBUFSIZE	0x4000
+static char *savebuf = 0;
+static int savebufsize = 0;
+static int savebufwptr =0;
+
+
+#define CACHEFILESIZE	(CACHEFILES_MAX * sizeof(struct cache_file))
+static struct cache_file *cachefile = 0;
+static int cachefilesize = 0;
+static int cachefilewptr = -1;
+static int cachefilecurrent = -1;
+
+static void free_savebuffer(void);
+static void free_cachefile_buffers(void);
+static void close_cachefile_write(int stop);
+
+
+OUR_YY_DECL
+{
+	int ret;
+
+	ret = real_yylex(yylval);
+
+        if (__loop_handling__ >0) {
+		/* we respawn yylex in a loop, while filling the cache files */
+		while (__loop_handling__ >0) {
+			ret = real_yylex(yylval);
+			if (ret == YY_NULL) {
+				__loop_handling__ = 0;
+				close_cachefile_write(savebufwptr);
+				free_cachefile_buffers();
+				free_savebuffer();
+				yyerror("EOF while in loop, probably 'done' missing");
+				return ret;
+			}
+		}
+		/* and again, to get the first token again */
+		ret = real_yylex(yylval);
+	}
+	return(ret);
+}
+
+static void free_savebuffer(void)
+{
+	if (savebuf) free(savebuf);
+	savebuf = 0;
+	savebufsize = 0;
+	savebufwptr = 0;
+}
+
+static void dumpout(char *s, int len)
+{
+	if ((savebufwptr + len) > savebufsize) {
+		do {
+			savebufsize += SAVEBUFSIZE;
+		} while ((savebufwptr + len) > savebufsize);
+		if (!savebuf)
+			savebuf = malloc(savebufsize);
+		else	savebuf = realloc(savebuf, savebufsize);
+	}
+	memcpy(savebuf+savebufwptr, s, len);
+	savebufwptr += len;
+}
+
+
+struct cache_file {
+	int start;	/* point behind the loop begin statement */
+	int stop;	/* point behind the loop end statement */
+	int rptr;
+	int parent;
+	YY_BUFFER_STATE yybuffer;
+	char *origfname;
+	int  firstline;
+	int  need_loop_back;
+	int looplimit;
+};
+
+static void free_cachefile_buffers(void)
+{
+	int i;
+	if (cachefile) {
+		for (i=0; i <cachefilewptr; i++)
+			if (cachefile[i].origfname) free(cachefile[i].origfname);
+		free(cachefile);
+		cachefile = 0;
+	}
+	cachefilesize = 0;
+	cachefilecurrent = cachefilewptr = -1;
+}
+
+static void create_cachefile(int start)
+{
+	struct cache_file *cf;
+
+	cachefilewptr++;
+	if (((cachefilewptr+1) * sizeof(struct cache_file)) > cachefilesize) {
+		cachefilesize += CACHEFILESIZE;
+		if (!cachefile)
+			cachefile = malloc(cachefilesize);
+		else	cachefile = realloc(cachefile, cachefilesize);
+	}
+	cf = cachefile + cachefilewptr;
+	cf->start = start; 
+	cf->stop = start;
+	cf->rptr = start;
+	cf->firstline = line_count;
+	cf->origfname = 0;
+#if 0
+	/* NOTE: The 'include_stack_ptr > 0' sanity check may be needed
+	   because of errors in do loops (to much 'done'), though this
+	   would be for sure a syntax error in the config file, but we
+	   got segfaults in the past and came not so far to report the
+	   error. Hence, we have to check if the segfaults happen again.
+	   Till then we leave the old code here in place.
+			--Hans, 980614
+	*/
+	if (include_stack_ptr > 0 && include_fnames[include_stack_ptr])
+#else
+	if (include_fnames[include_stack_ptr])
+#endif
+		cf->origfname = strdup(include_fnames[include_stack_ptr]);
+	cf->parent = cachefilecurrent;
+	cachefilecurrent = cachefilewptr;
+}
+
+static void close_cachefile_write(int stop)
+{
+	if (!cachefile || cachefilecurrent <0)
+		return;
+	cachefile[cachefilecurrent].stop = stop;
+	cachefilecurrent = cachefile[cachefilecurrent].parent;
+}
+
+
+static int cachefile_read(char *buf, int size, int cfile)
+{
+	struct cache_file *cf = cachefile+cfile;
+
+	if (!cachefile || cachefilecurrent <0) return 0;
+	if (cf->rptr+size >= cf->stop)
+		size = cf->stop - cf->rptr;
+	if (size <= 0) return 0;
+	memcpy(buf, savebuf + cf->rptr, size);
+	cf->rptr += size;
+	return size;
+}
+
+
+static void enter_cachefile(int cfile)
+{
+	struct cache_file *cf;
+
+	if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+		yyerror("Loops nested too deeply" );
+		return;
+	}
+	if (!cachefile) {
+		yyerror("mismatching loop begin/end \n");
+		return;
+	}
+	cachefilecurrent = cfile;
+	if (config_check_only>1)
+		c_printf("CONF: opened cache file %d\n", cachefilecurrent);
+	include_lines[include_stack_ptr] = line_count;
+	include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+	include_stack_ptr++;
+	cf = cachefile + cachefilecurrent;
+	cf->looplimit = LOOP_LIMIT;
+	cf->rptr = cf->start;
+	if (cf->origfname)
+		include_fnames[include_stack_ptr] = strdup(cf->origfname);
+	else	include_fnames[include_stack_ptr] = 0;
+	line_count = cf->firstline;
+	(int)yyin = cachefilecurrent +1;
+	include_stack[include_stack_ptr] = yy_create_buffer( yyin, cf->stop - cf->start +2);
+	yy_switch_to_buffer(include_stack[include_stack_ptr]);
+}
+
+
+static int chachefile_wrap(void)
+{
+	struct cache_file *cf;
+	int cfile;
+
+	/* we come her from yywrap, when we got an EOF on the cache file */
+	
+	if (include_stack_ptr <= 0 || !cachefile || cachefilecurrent <0) return 0;
+	cfile = cachefilecurrent;
+	cf = cachefile + cfile;
+	if (cf->need_loop_back) {
+		if (--cf->looplimit <0) {
+			yyerror("loop limit of %d loops exceeded\n", LOOP_LIMIT);
+			cf->need_loop_back = 0;
+		}
+		else {
+			cf->rptr = cf->start;
+			line_count = cf->firstline;
+			return(0);
+		}
+	}
+	cachefilecurrent = cf->parent;
+	yy_switch_to_buffer(include_stack[include_stack_ptr-1] );
+	yy_delete_buffer(include_stack[include_stack_ptr]);
+	if (config_check_only>1)
+		c_printf("CONF: closed cache file %d\n", cfile);
+	include_stack_ptr--;
+	line_count=include_lines[include_stack_ptr];
+	if (cfile > 0) {
+		/* when in inner loop, we have been executed from
+		 * the copy, but the main cache file still is positioned
+		 * directly behind the 'while__ ()' in the original.
+		 * we have to skip this until 'done'.
+		 * This can simply done by setting __active__=0,
+		 * because the 'while__' has done an extra push__active()
+		 * and the 'done' in the main cache file will do pop__active()
+		 */
+		__active__ = 0;
+	}
+	if (cachefilecurrent <0) {
+		/* end of loop handling */
+		__loop_handling__ = 0;
+		free_cachefile_buffers();
+		free_savebuffer();
+	}
+	return(0);
+}
+
+void tell_lexer_loop(int cfile, int value)
+{
+	__active__ = value !=0;
+	if (!cachefile) return;
+	if (__active__ && cachefilecurrent != cfile) {
+		/* we have to open a deeper nested cache file */
+		enter_cachefile(cfile);
+	}
+	cachefile[cfile].need_loop_back = __active__;
+	return;
+}
+
+
+static int dump_input(int rulenum)
+{
+	static int lastrule=0;
+	static int lastchar = '\n';
+	int savebufwptr_ = savebufwptr;
+	int skip_action = 1;
+
+	switch (rulenum) {
+		case INCLUDE_RULE_NUM: {
+			dumpout("#",1); /* comment out the include statement*/
+			skip_action = 0;
+			break;
+		}
+	}
+
+	if (rulenum != COMMENT_RULE_NUM ) {
+		if (rulenum == WHITESPACE_RULE_NUM) {
+			if (lastchar != '\n') {
+				dumpout(" ",1);
+				lastchar = ' ';
+			}
+		}
+		else {
+			dumpout(yytext,yyleng);
+			lastchar = yytext[yyleng-1];
+		}
+	}
+	else {
+		dumpout("#\n",2);
+		lastchar = '\n';
+		line_count++;
+	}
+	lastrule = rulenum;
+	switch (rulenum) {
+		case NEWLINE__RULE_NUM: {
+			line_count++;
+			break;
+		}
+		case INCLUDEFILE_RULE_NUM: {
+			if (__next_ITEM_for_me__ == 2) {
+				dumpout("\n",1);
+				lastchar = '\n';
+				skip_action = 0;
+			}
+			break;
+		}
+		case LOOP_RULE_NUM: {
+			char buf[32];
+			create_cachefile(savebufwptr_);
+			sprintf(buf, "__yy__ %d, ", cachefilecurrent);
+			dumpout(buf, strlen(buf));
+			break;
+		}
+		case DONE_RULE_NUM: {
+			close_cachefile_write(savebufwptr);
+			if (cachefilecurrent <0) {
+				/* finished all cashing,
+				 * starting working phase */
+				__loop_handling__ = -1;
+				enter_cachefile(0);
+			}
+		}
+	}
+	return skip_action;
+}
+
+static void enter_macrofile(char *variable)
+{
+	char *macrobuffer;
+	if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+		yyerror("macrocall ... nested too deeply" );
+		return;
+	}
+        macrobuffer = checked_getenv(variable);
+	if (!macrobuffer) {
+		yywarn("macro '%s' not found \n", variable);
+		return;
+	}
+	if (config_check_only>1)
+		c_printf("CONF: opened macro file %s\n", variable);
+	include_lines[include_stack_ptr] = line_count;
+	include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
+	include_stack_ptr++;
+	include_macbuf[include_stack_ptr] =
+		include_fnames[include_stack_ptr] = strdup(macrobuffer);
+	(int)yyin = MACROFILE;
+	include_stack[include_stack_ptr] = yy_create_buffer( yyin, strlen(macrobuffer) +2);
+	yy_switch_to_buffer(include_stack[include_stack_ptr]);
+}
+
+static int macrofile_wrap(void)
+{
+	/* we come her from yywrap, when we got an EOF on the macro file */
+	
+	if (include_stack_ptr <= 0) return 0;
+	yy_switch_to_buffer(include_stack[include_stack_ptr-1] );
+	yy_delete_buffer(include_stack[include_stack_ptr]);
+	free(include_macbuf[include_stack_ptr]);
+	if (config_check_only>1)
+		c_printf("CONF: closed macro file\n");
+	include_stack_ptr--;
+	line_count=include_lines[include_stack_ptr];
+	return(0);
+}
+
+
+static int macrofile_read(char *buf, int size)
+{
+	int len;
+	char *macroptr = include_fnames[include_stack_ptr];
+	len = strlen(macroptr);
+	if (!len) return 0;
+	if (size > len) size = len;
+	memcpy(buf, macroptr, size);
+	include_fnames[include_stack_ptr] +=size;
+	return size;
+}
+
+
+
+#endif /* USE_LOOP_HANDLING */
diff -Nur dosemu-1.0.1/src/base/init/lexer.l.rej dosemu-1.0.1-mauspatch/src/base/init/lexer.l.rej
--- dosemu-1.0.1/src/base/init/lexer.l.rej	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/src/base/init/lexer.l.rej	Thu Sep 14 22:19:58 2000
@@ -0,0 +1,16 @@
+***************
+*** 376,381 ****
+  dosemumap               RETURN(DOSEMUMAP);
+  logbufsize              RETURN(LOGBUFSIZE);
+  logfilesize		RETURN(LOGFILESIZE);
+  
+  	/* sillyint values */
+  use_sigio		RETURN(USE_SIGIO);
+--- 376,382 ----
+  dosemumap               RETURN(DOSEMUMAP);
+  logbufsize              RETURN(LOGBUFSIZE);
+  logfilesize		RETURN(LOGFILESIZE);
++ stime			RETURN(STIME);
+  
+  	/* sillyint values */
+  use_sigio		RETURN(USE_SIGIO);
diff -Nur dosemu-1.0.1/src/base/init/parser.y dosemu-1.0.1-mauspatch/src/base/init/parser.y
--- dosemu-1.0.1/src/base/init/parser.y	Sun Mar  5 21:31:38 2000
+++ dosemu-1.0.1-mauspatch/src/base/init/parser.y	Thu Sep 14 22:19:58 2000
@@ -298,6 +298,8 @@
 	/* hardware ram mapping */
 %token HARDWARE_RAM
         /* Sound Emulation */
+%token STIME
+        /* Dosemu set unix time */
 %token SB_BASE SB_IRQ SB_DMA SB_MIXER SB_DSP MPU_BASE
 	/* CD-ROM */
 %token CDROM
@@ -734,6 +736,13 @@
 		      yyerror("Can not change hardware ram access settings in user config file");
 		    }
                    '{' hardware_ram_flags '}'
+                | STIME expression
+                    { IFCLASS(CL_PORT);
+                    if (priv_lvl)
+                      yyerror("Can not change stime settings in user config file");
+                    else
+                      config.int1a_allow_stime = ($2 & 0xf);
+                    }
 		| FEATURE '{' expression '=' expression '}'
 		    {
 			handle_features($3, $5);
diff -Nur dosemu-1.0.1/src/base/init/parser.y.orig dosemu-1.0.1-mauspatch/src/base/init/parser.y.orig
--- dosemu-1.0.1/src/base/init/parser.y.orig	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/src/base/init/parser.y.orig	Sun Mar  5 21:31:38 2000
@@ -0,0 +1,3199 @@
+/* 
+ * (C) Copyright 1992, ..., 2000 the "DOSEMU-Development-Team".
+ *
+ * for details see file COPYING in the DOSEMU distribution
+ */
+
+/* parser.y
+ *
+ * Parser version 1     ... before 0.66.5
+ * Parser version 2     at state of 0.66.5   97/05/30
+ * Parser version 3     at state of 0.97.0.1 98/01/03
+ *
+ * Note:  starting with version 2, you may protect against version 3 via
+ *
+ *   ifdef parser_version_3
+ *     # version 3 style parser
+ *   else
+ *     # old style parser
+ *   endif
+ *
+ * Note2: starting with version 3 you _need_ atleast _one_ statement such as
+ *
+ *   $XYZ = "something"
+ *
+ * to make the 'new version style check' happy, else dosemu will abort.
+ */
+
+%{
+
+#define PARSER_VERSION_STRING "parser_version_3"
+
+#include <stdlib.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <setjmp.h>
+#include <sys/stat.h>                    /* structure stat       */
+#include <unistd.h>                      /* prototype for stat() */
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+#ifdef __linux__
+#include <mntent.h>
+#endif
+
+#include "config.h"
+#include "emu.h"
+#include "disks.h"
+#include "port.h"
+#define allow_io	port_allow_io
+#include "lpt.h"
+#include "video.h"
+#include "mouse.h"
+#include "serial.h"
+#include "timers.h"
+#include "keymaps.h"
+#include "memory.h"
+#include "utilities.h"
+
+#include "parsglob.h"
+#include "lexer.h"
+
+
+#define USERVAR_PREF	"dosemu_"
+static int user_scope_level;
+
+static int after_secure_check = 0;
+static serial_t *sptr;
+static serial_t nullser;
+static mouse_t *mptr;
+static mouse_t nullmouse;
+static int c_ser = 0;
+static int c_mouse = 0;
+
+static struct disk *dptr;
+static struct disk nulldisk;
+static int c_hdisks = 0;
+static int c_fdisks = 0;
+
+int dexe_running = 0;
+static int dexe_forbid_disk = 1;
+static int dexe_secure = 1;
+char own_hostname[128];
+
+extern struct printer lpt[NUM_PRINTERS];
+static struct printer *pptr;
+static struct printer nullptr;
+static int c_printers = 0;
+
+static int ports_permission = IO_RDWR;
+static unsigned int ports_ormask = 0;
+static unsigned int ports_andmask = 0xFFFF;
+static unsigned int portspeed = 0;
+static char dev_name[255]= "";
+
+static int errors = 0;
+static int warnings = 0;
+
+static int priv_lvl = 0;
+static int saved_priv_lvl = 0; 
+
+
+static char *file_being_parsed;
+
+			/* this to ensure we are parsing a new style */
+static int parser_version_3_style_used = 0;
+#define CONFNAME_V3USED "version_3_style_used"
+
+	/* external procedures */
+
+extern int exchange_uids(void);
+extern int yylex(); /* exact argument types depend on the way you call bison */
+extern void tell_lexer_if(int value);
+extern void tell_lexer_loop(int cfile, int value);
+extern int parse_debugflags(const char *s, unsigned char flag);
+extern void register_port_traceing(ioport_t firstport, ioport_t lastport);
+extern void clear_port_traceing(void);
+
+	/* local procedures */
+
+void yyerror(char *, ...);
+void yywarn(char *, ...);
+void keyb_layout(int value);
+static void start_ports(void);
+static void start_mouse(void);
+static void stop_mouse(void);
+static void start_debug(void);
+static void start_video(void);
+static void stop_video(void);
+static void set_vesamodes(int width, int height, int color_bits);
+static void start_ttylocks(void);
+static void stop_ttylocks(void);
+static void start_serial(void);
+static void stop_serial(void);
+static void start_printer(void);
+static void stop_printer(void);
+static void start_keyboard(void);
+static void keytable_start(int layout);
+static void keytable_stop(void);
+static void keyb_mod(int wich, int keynum);
+static void dump_keytables_to_file(char *name);
+static void start_terminal(void);
+static void stop_terminal(void);
+static void start_disk(void);
+static void do_part(char *);
+static void start_bootdisk(void);
+static void start_floppy(void);
+static void stop_disk(int token);
+static FILE* open_file(char* filename);
+static void close_file(FILE* file);
+static void write_to_syslog(char *message);
+static int set_hardware_ram(int addr);
+static void set_irq_value(int bits, int i1);
+static void set_irq_range(int bits, int i1, int i2);
+extern void append_pre_strokes(unsigned char *s);
+char *get_config_variable(char *name);
+int define_config_variable(char *name);
+static int undefine_config_variable(char *name);
+static void check_user_var(char *name);
+static char *run_shell(char *command);
+static int for_each_handling(int loopid, char *varname, char *delim, char *list);
+char *checked_getenv(const char *name);
+static void enter_user_scope(int incstackptr);
+static void leave_user_scope(int incstackptr);
+static void handle_features(int which, int value);
+
+	/* class stuff */
+#define IFCLASS(m) if (is_in_allowed_classes(m))
+
+#define CL_ALL			-1
+#define CL_NICE		    0x100
+#define CL_VAR		    0x200
+#define CL_FILEEXT	    0x400
+#define CL_FLOPPY	    0x800
+#define CL_BOOT		   0x1000
+#define CL_VPORT	   0x2000
+#define CL_SECURE	   0x4000
+#define CL_DPMI		   0x8000
+#define CL_VIDEO	  0x10000
+#define CL_PORT		  0x20000
+#define CL_DISK		  0x40000
+#define CL_X		  0x80000
+#define CL_SOUND	 0x100000
+#define CL_IRQ		 0x200000
+#define CL_DEXE		 0x400000
+#define CL_PRINTER	 0x800000
+#define CL_HARDRAM	0x1000000
+#define CL_SHELL	0x2000000
+
+static int is_in_allowed_classes(int mask);
+
+	/* variables in lexer.l */
+
+extern FILE* yyin;
+extern void yyrestart(FILE *input_file);
+%}
+
+%start lines
+
+%union {
+	int i_value;
+	char *s_value;
+	float r_value;
+	long long all_value;
+	ExprType t_value;
+};
+
+
+%token <i_value> INTEGER L_OFF L_ON L_AUTO L_YES L_NO CHIPSET_TYPE
+%token <i_value> CHARSET_TYPE KEYB_LAYOUT
+%token <r_value> REAL
+%token <s_value> STRING VARIABLE
+
+	/* needed for expressions */
+%token EXPRTEST
+%token INTCAST REALCAST
+%left AND_OP OR_OP XOR_OP SHR_OP SHL_OP
+%left NOT_OP /* logical NOT */
+%left EQ_OP GE_OP LE_OP '=' '<' '>' NEQ_OP
+%left STR_EQ_OP STR_NEQ_OP
+%left L_AND_OP L_OR_OP
+%left '+' '-'
+%left '*' '/'
+%left UMINUS UPLUS BIT_NOT_OP
+
+%token	STRLEN STRTOL STRNCMP STRCAT STRPBRK STRSPLIT STRCHR STRRCHR STRSTR
+%token	STRDEL STRSPN STRCSPN SHELL
+%token	DEFINED
+%type	<i_value> expression
+%type	<s_value> string_expr variable_content strarglist strarglist_item
+
+	/* flow control */
+%token DEFINE UNDEF IFSTATEMENT WHILESTATEMENT FOREACHSTATEMENT
+%token <i_value> ENTER_USER_SPACE LEAVE_USER_SPACE
+
+	/* variable handling */
+%token CHECKUSERVAR
+
+	/* main options */
+%token DOSBANNER FASTFLOPPY TIMINT HOGTHRESH SPEAKER IPXSUPPORT NOVELLHACK
+%token VNET
+%token DEBUG MOUSE SERIAL COM KEYBOARD TERMINAL VIDEO ALLOWVIDEOPORT EMURETRACE TIMER
+%token MATHCO CPU CPUSPEED RDTSC BOOTA BOOTB BOOTC L_XMS L_DPMI PORTS DISK DOSMEM PRINTER
+%token L_EMS L_UMB EMS_SIZE EMS_FRAME TTYLOCKS L_SOUND
+%token L_SECURE
+%token DEXE ALLOWDISK FORCEXDOS XDOSONLY
+%token ABORT WARN
+%token BOOTDISK L_FLOPPY EMUSYS EMUBAT EMUINI L_X
+%token DOSEMUMAP LOGBUFSIZE LOGFILESIZE MAPPINGDRIVER
+	/* speaker */
+%token EMULATED NATIVE
+	/* keyboard */
+%token KEYBINT RAWKEYBOARD
+%token PRESTROKE
+%token KEYTABLE SHIFT ALT NUMPAD DUMP
+%token DGRAVE DACUTE DCIRCUM DTILDE DBREVE DABOVED DDIARES DABOVER DDACUTE DCEDILLA DIOTA DOGONEK DCARON
+	/* ipx */
+%token NETWORK PKTDRIVER
+        /* lock files */
+%token DIRECTORY NAMESTUB BINARY
+	/* serial */
+%token BASE IRQ INTERRUPT DEVICE CHARSET  BAUDRATE
+	/* mouse */
+%token MICROSOFT MS3BUTTON LOGITECH MMSERIES MOUSEMAN HITACHI MOUSESYSTEMS BUSMOUSE PS2
+%token INTERNALDRIVER EMULATE3BUTTONS CLEARDTR
+	/* x-windows */
+%token L_DISPLAY L_TITLE ICON_NAME X_KEYCODE X_KEYCODE_AUTO X_BLINKRATE X_SHARECMAP X_MITSHM X_FONT
+%token X_FIXED_ASPECT X_ASPECT_43 X_LIN_FILT X_BILIN_FILT X_MODE13FACT X_WINSIZE
+%token X_GAMMA VGAEMU_MEMSIZE VESAMODE X_LFB X_PM_INTERFACE X_MGRAB_KEY
+	/* video */
+%token VGA MGA CGA EGA NONE CONSOLE GRAPHICS CHIPSET FULLREST PARTREST
+%token MEMSIZE VBIOS_SIZE_TOK VBIOS_SEG VBIOS_FILE VBIOS_COPY VBIOS_MMAP DUALMON
+%token FORCE_VT_SWITCH PCI
+	/* terminal */
+%token UPDATEFREQ UPDATELINES COLOR ESCCHAR
+/* %token UPDATEFREQ UPDATELINES COLOR CORNER METHOD NORMAL XTERM NCURSES FAST */
+	/* debug */
+%token IO PORT CONFIG READ WRITE KEYB PRINTER WARNING GENERAL HARDWARE
+%token L_IPC SOUND
+%token TRACE CLEAR
+
+	/* printer */
+%token COMMAND TIMEOUT OPTIONS L_FILE
+	/* disk */
+%token L_PARTITION BOOTFILE WHOLEDISK THREEINCH FIVEINCH ATAPI READONLY LAYOUT
+%token SECTORS CYLINDERS TRACKS HEADS OFFSET HDIMAGE DISKCYL4096
+	/* ports/io */
+%token RDONLY WRONLY RDWR ORMASK ANDMASK RANGE FAST
+	/* Silly interrupts */
+%token SILLYINT USE_SIGIO
+	/* hardware ram mapping */
+%token HARDWARE_RAM
+        /* Sound Emulation */
+%token SB_BASE SB_IRQ SB_DMA SB_MIXER SB_DSP MPU_BASE
+	/* CD-ROM */
+%token CDROM
+	/* ASPI driver */
+%token ASPI DEVICETYPE TARGET
+	/* features */
+%token FEATURE
+
+	/* we know we have 1 shift/reduce conflict :-( 
+	 * and tell the parser to ignore that */
+	/* %expect 1 */
+
+/* %type <i_value> mem_bool irq_bool bool speaker method_val color_val floppy_bool */
+%type <i_value> mem_bool irq_bool bool speaker color_val floppy_bool
+
+%%
+
+lines		: line
+		| lines line
+		| lines optdelim line
+		;
+
+optdelim	: ';'
+		| optdelim ';'
+		;
+
+line		: HOGTHRESH expression	{ IFCLASS(CL_NICE) config.hogthreshold = $2; }
+		| DEFINE STRING		{ IFCLASS(CL_VAR){ define_config_variable($2);} free($2); }
+		| UNDEF STRING		{ IFCLASS(CL_VAR){ undefine_config_variable($2);} free($2); }
+		| IFSTATEMENT '(' expression ')' {
+			/* NOTE:
+			 * We _need_ absolutely to return to state stack 0
+			 * because we 'backward' modify the input stream for
+			 * the parser (in lexer). Hence, _if_ the parser needs
+			 * to read one token more than needed, we are lost,
+			 * because we can't discard it. So please, don't
+			 * play with the grammar without knowing what you do.
+			 * The ')' _will_ return to state stack 0, but fiddling
+			 * with brackets '()' in the underlaying 'expression'
+			 * rules may distroy this.
+			 *                          -- Hans 971231
+			 */
+			tell_lexer_if($3);
+		}
+		/* Note: the below syntax of the while__yy__ statement
+		 * is internal and _not_ visible out side.
+		 * The visible syntax is:
+		 *	while ( expression )
+		 *	   <loop contents>
+		 *	done
+		 */
+		| WHILESTATEMENT INTEGER ',' '(' expression ')' {
+			tell_lexer_loop($2, $5);
+		}
+		| FOREACHSTATEMENT INTEGER ',' VARIABLE '(' string_expr ',' strarglist ')' {
+			tell_lexer_loop($2, for_each_handling($2,$4,$6,$8));
+			free($4); free($6); free($8);
+		}
+		| SHELL '(' strarglist ')' {
+			IFCLASS(CL_SHELL) {
+				char *s = run_shell($3);
+				if (s) free(s);
+			}
+			else {
+				yyerror("not in allowed class to execute SHELL(%s)",$3);
+			}
+			free($3);
+		}
+		| ENTER_USER_SPACE { enter_user_scope($1); }
+		| LEAVE_USER_SPACE { leave_user_scope($1); }
+		| VARIABLE '=' strarglist {
+		    if (!parser_version_3_style_used) {
+			parser_version_3_style_used = 1;
+			define_config_variable(CONFNAME_V3USED);
+		    }
+		    if ((strpbrk($1, "uhc") == $1) && ($1[1] == '_'))
+			yyerror("reserved variable %s can't be set\n", $1);
+		    else {
+			if (user_scope_level) {
+			    char *s = malloc(strlen($1)+sizeof(USERVAR_PREF));
+			    strcpy(s, USERVAR_PREF);
+			    strcat(s,$1);
+			    setenv(s, $3, 1);
+			    free(s);
+			}
+			else IFCLASS(CL_VAR) setenv($1, $3, 1);
+		    }
+		    free($1); free($3);
+		}
+		| CHECKUSERVAR check_user_var_list
+		| EXPRTEST expression {
+		    if (EXPRTYPE($2) == TYPE_REAL)
+			c_printf("CONF TESTING: exprtest real %f %08x\n", VAL_R($2), $2);
+		    else
+			c_printf("CONF TESTING: exprtest int %d %08x\n", VAL_I($2), $2);
+		}
+		/* abandoning 'single' abort due to shift/reduce conflicts
+		   Just use ' abort "" '
+		| ABORT			{ leavedos(99); }
+		*/
+		| ABORT strarglist
+		    { if ($2[0]) fprintf(stderr,"CONF aborted with: %s\n", $2);
+			exit(99);
+		      leavedos(99);
+		    }
+		| WARN strarglist	{ c_printf("CONF: %s\n", $2); free($2); }
+ 		| EMUSYS string_expr
+		    { IFCLASS(CL_FILEEXT){
+		    config.emusys = $2;
+		    c_printf("CONF: config.emusys = '%s'\n", $2);
+		    }}
+		| EMUSYS '{' string_expr '}'
+		    { IFCLASS(CL_FILEEXT){
+		    config.emusys = $3;
+		    c_printf("CONF: config.emusys = '%s'\n", $3);
+		    }}
+		| DOSEMUMAP string_expr
+		    {
+#ifdef USE_MHPDBG
+		    DOSEMU_MAP_PATH = $2;
+		    c_printf("CONF: dosemu.map path = '%s'\n", $2);
+#else
+		    free($2);
+#endif
+		    }
+		| MAPPINGDRIVER string_expr
+		    {
+		    config.mappingdriver = $2;
+		    c_printf("CONF: mapping driver = '%s'\n", $2);
+		    }
+ 		| EMUBAT string_expr
+		    { IFCLASS(CL_FILEEXT){
+		    config.emubat = $2;
+		    c_printf("CONF: config.emubat = '%s'\n", $2);
+                    }}
+                | EMUINI string_expr
+                    { IFCLASS(CL_FILEEXT){
+                    config.emuini = $2;
+                    c_printf("CONF: config.emuini = '%s'\n", $2);
+                    }}
+                | EMUINI '{' string_expr '}'
+                    { IFCLASS(CL_FILEEXT){
+                    config.emuini = $3;
+                    c_printf("CONF: config.emuini = '%s'\n", $3);
+		    }}
+		| EMUBAT '{' string_expr '}'
+		    { IFCLASS(CL_FILEEXT){
+		    config.emubat = $3;
+		    c_printf("CONF: config.emubat = '%s'\n", $3);
+		    }}
+		| FASTFLOPPY floppy_bool
+			{ IFCLASS(CL_FLOPPY){ 
+			config.fastfloppy = $2;
+			c_printf("CONF: fastfloppy = %d\n", config.fastfloppy);
+			}}
+		| CPU expression
+			{
+			extern int cpu_override(int);
+			int cpu = cpu_override (($2%100)==86?($2/100)%10:0);
+			if (cpu > 0) {
+				c_printf("CONF: CPU set to %d86\n",cpu);
+				vm86s.cpu_type = cpu;
+			}
+			else
+				yyerror("error in CPU user override\n");
+			}
+		| CPU EMULATED
+			{
+			/* in 1.0 removed, in 1.1 kept */
+			}
+		| CPUSPEED expression
+			{ 
+#if 0 /* no longer used, but left in for dosemu.conf compatibility */
+			if (config.realcpu >= CPU_586) {
+			  config.cpu_spd = ((double)LLF_US)/TOF($2);
+			  config.cpu_tick_spd = ((double)LLF_TICKS)/TOF($2);
+			  c_printf("CONF: CPU speed = %g\n", ((double)TOF($2)));
+			}
+#endif
+			}
+		| CPUSPEED INTEGER INTEGER
+			{ 
+#if 0 /* no longer used, but left in for dosemu.conf compatibility */
+			if (config.realcpu >= CPU_586) {
+			  config.cpu_spd = (LLF_US*$3)/$2;
+			  config.cpu_tick_spd = (LLF_TICKS*$3)/$2;
+			  c_printf("CONF: CPU speed = %d/%d\n", $2, $3);
+			}
+#endif
+			}
+		| RDTSC bool
+		    {
+		    if (config.smp && ($2!=0)) {
+			c_printf("CONF: Denying use of pentium timer on SMP machine\n");
+			config.rdtsc = 0;
+		    }
+		    else if (config.realcpu>=CPU_586) {
+			config.rdtsc = ($2!=0);
+			c_printf("CONF: %sabling use of pentium timer\n",
+				(config.rdtsc?"En":"Dis"));
+		    }
+		    else
+			c_printf("CONF: Ignoring 'rdtsc' statement\n");
+		    }
+		| PCI bool
+		    {
+		    config.pci = ($2!=0);
+		    }
+		| BOOTA
+                    { IFCLASS(CL_BOOT){
+		      if (priv_lvl)
+			yyerror("bootA is illegal in user config file");
+		      config.hdiskboot = 0;
+		    }}
+		| BOOTC
+                    { IFCLASS(CL_BOOT){
+		      if (priv_lvl)
+			yyerror("bootC is illegal in user config file");
+		      config.hdiskboot = 1;
+		    }}
+		| BOOTB
+                    { IFCLASS(CL_BOOT){
+		      if (priv_lvl)
+			yyerror("bootB is illegal in user config file\n");
+		      config.hdiskboot = 2;
+		    }}
+		| TIMINT bool
+		    {
+		    config.timers = $2;
+		    c_printf("CONF: timint %s\n", ($2) ? "on" : "off");
+		    }
+		| TIMER expression
+		    {
+		    config.freq = $2;
+		    config.update = 1000000 / $2;
+		    c_printf("CONF: timer freq=%d, update=%d\n",config.freq,config.update);
+		    }
+		| LOGBUFSIZE expression
+		    {
+		      extern int logbuf_size;
+		      extern char *logbuf, *logptr;
+		      char *b;
+		      flush_log();
+		      b = malloc($2+1024);
+		      if (!b) {
+			error("cannot get logbuffer\n");
+			exit(1);
+		      }
+		      logptr = logbuf = b;
+		      logbuf_size = $2;
+		    }
+		| LOGFILESIZE expression
+		    {
+		      extern int logfile_limit;
+		      logfile_limit = $2;
+		    }
+		| DOSBANNER bool
+		    {
+		    config.dosbanner = $2;
+		    c_printf("CONF: dosbanner %s\n", ($2) ? "on" : "off");
+		    }
+		| ALLOWVIDEOPORT bool
+		    { IFCLASS(CL_VPORT){
+		    if ($2 && !config.allowvideoportaccess && priv_lvl)
+		      yyerror("Can not enable video port access in user config file");
+		    config.allowvideoportaccess = $2;
+		    c_printf("CONF: allowvideoportaccess %s\n", ($2) ? "on" : "off");
+		    }}
+		| EMURETRACE bool
+		    { IFCLASS(CL_VPORT){
+		    if ($2 && !config.emuretrace && priv_lvl)
+		      yyerror("Can not modify video port access in user config file");
+		    config.emuretrace = $2;
+		    c_printf("CONF: emu_retrace %s\n", ($2) ? "on" : "off");
+		    }}
+		| L_EMS { config.ems_size=0; }  '{' ems_flags '}'
+		| L_EMS mem_bool
+		    {
+		    config.ems_size = $2;
+		    if ($2 > 0) c_printf("CONF: %dk bytes EMS memory\n", $2);
+		    }
+		| L_XMS mem_bool
+		    {
+		    config.xms_size = $2;
+		    if ($2 > 0) c_printf("CONF: %dk bytes XMS memory\n", $2);
+		    }
+		| L_UMB bool
+		    {
+		    config.max_umb = $2;
+		    if ($2 > 0) c_printf("CONF: maximize umb's %s\n", ($2) ? "on" : "off");
+		    }
+		| L_SECURE bool
+		    { IFCLASS(CL_SECURE){
+		    if (priv_lvl && config.secure && (! $2))
+			yyerror("secure option is illegal in user config file");
+		    config.secure = $2;
+		    if (config.secure > 0) c_printf("CONF: security %s\n", ($2) ? "on" : "off");
+		    }}
+		| L_DPMI mem_bool
+		    { IFCLASS(CL_DPMI){
+		    config.dpmi = $2;
+		    c_printf("CONF: DPMI-Server %s\n", ($2) ? "on" : "off");
+		    }}
+		| DOSMEM mem_bool	{ config.mem_size = $2; }
+		| MATHCO bool		{ config.mathco = $2; }
+		| IPXSUPPORT bool	{ config.ipxsup = $2; }
+		    {
+		    config.ipxsup = $2;
+		    c_printf("CONF: IPX support %s\n", ($2) ? "on" : "off");
+		    }
+		| PKTDRIVER NOVELLHACK	{ config.pktflags = 1; }
+		| VNET bool	{ config.vnet = $2; }
+		| SPEAKER speaker
+		    {
+		    if ($2 == SPKR_NATIVE) {
+                      c_printf("CONF: allowing speaker port access!\n");
+#if 0  /* this is now handled in timers.c */
+		      allow_io(0x42, 1, IO_RDWR, 0, 0xFFFF, 1, NULL);
+		      allow_io(0x61, 1, IO_RDWR, 0, 0xFFFF, 1, NULL);
+#endif
+		      }
+		    else
+                      c_printf("CONF: not allowing speaker port access\n");
+		    config.speaker = $2;
+		    }
+		| VIDEO
+		    { IFCLASS(CL_VIDEO) start_video(); }
+		  '{' video_flags '}'
+		    { stop_video(); }
+		| CHARSET CHARSET_TYPE	{ config.term_charset = $2; }
+		| TERMINAL
+		    { start_terminal(); }
+                  '{' term_flags '}'
+		    { stop_terminal(); }
+		| DEBUG strarglist {
+			parse_debugflags($2, 1);
+			free($2);
+		}
+		| DEBUG
+		    { start_debug(); }
+		  '{' debug_flags '}'
+		| MOUSE
+		    { start_mouse(); }
+		  '{' mouse_flags '}'
+		    { stop_mouse(); }
+                | TTYLOCKS
+                    { start_ttylocks(); }
+                  '{' ttylocks_flags '}'
+                    { stop_ttylocks(); }
+		| SERIAL
+		    { start_serial(); }
+		  '{' serial_flags '}'
+		    { stop_serial(); }
+		| KEYBOARD
+		    { start_keyboard(); }
+	          '{' keyboard_flags '}'
+		| KEYTABLE KEYB_LAYOUT
+			{keytable_start($2);}
+		  '{' keyboard_mods '}'
+		  	{keytable_stop();}
+ 		| PRESTROKE string_expr
+		    {
+		    append_pre_strokes($2);
+		    c_printf("CONF: appending pre-strokes '%s'\n", $2);
+		    free($2);
+		    }
+		| KEYTABLE DUMP string_expr {
+			dump_keytables_to_file($3);
+			free($3);
+		    }
+		| PORTS
+		    { IFCLASS(CL_PORT) start_ports(); }
+		  '{' port_flags '}'
+		| TRACE PORTS '{' trace_port_flags '}'
+		| DISK
+		    { IFCLASS(CL_DISK) start_disk(); }
+		  '{' disk_flags '}'
+		    { stop_disk(DISK); }
+		| BOOTDISK
+		    { IFCLASS(CL_BOOT) start_bootdisk(); }
+		  '{' disk_flags '}'
+		    { stop_disk(BOOTDISK); }
+		| L_FLOPPY
+		    { IFCLASS(CL_FLOPPY) start_floppy(); }
+		  '{' disk_flags '}'
+		    { stop_disk(L_FLOPPY); }
+                | CDROM '{' string_expr '}'
+                    { IFCLASS(CL_DISK){
+		    static int which = 0;
+		    if (which >= 3) {
+			c_printf("CONF: too many cdrom drives defined\n");
+			free($3);
+		    }
+		    else {
+			Path_cdrom[which] = $3;
+			c_printf("CONF: cdrom MSCD000%d on %s\n", which+1 ,$3);
+			which++;
+		    }
+		    }}
+                | ASPI '{' string_expr DEVICETYPE string_expr TARGET expression '}'
+                    { IFCLASS(CL_DISK){
+#ifdef ASPI_SUPPORT
+		    extern char *aspi_add_device(char *name, char *devtype, int);
+		    char *s = aspi_add_device($3, $5, $7);
+		    if (s) {
+			c_printf("CONF: aspi available for %s\n", s);
+			free(s);
+		    }
+		    else c_printf("CONF: aspi device %s not available\n", $3);
+#endif
+		    free($3);
+		    free($5);
+		    }}
+		| PRINTER
+		    { IFCLASS(CL_PRINTER) start_printer(); }
+		  '{' printer_flags '}'
+		    { stop_printer(); }
+		| L_X { IFCLASS(CL_X); } '{' x_flags '}'
+		| L_SOUND bool	{ if (! $2) config.sb_irq = 0; }
+                | L_SOUND { IFCLASS(CL_SOUND); } '{' sound_flags '}'
+		| SILLYINT
+                    { IFCLASS(CL_IRQ) config.sillyint=0; }
+                  '{' sillyint_flags '}'
+		| SILLYINT irq_bool
+                    { IFCLASS(CL_IRQ) if ($2) {
+		        config.sillyint = 1 << $2;
+		        c_printf("CONF: IRQ %d for irqpassing\n", $2);
+		      }
+		    }
+		| DEXE { IFCLASS(CL_DEXE); } '{' dexeflags '}'
+		| HARDWARE_RAM
+                    { IFCLASS(CL_HARDRAM);
+		    if (priv_lvl)
+		      yyerror("Can not change hardware ram access settings in user config file");
+		    }
+                   '{' hardware_ram_flags '}'
+		| FEATURE '{' expression '=' expression '}'
+		    {
+			handle_features($3, $5);
+		    }
+		| STRING
+		    { yyerror("unrecognized command '%s'", $1); free($1); }
+		| error
+		;
+
+	/* expressions */
+expression:
+		  INTEGER {TYPINT($$);}
+		| REAL {TYPREAL($$);}
+		| expression '+' expression
+			{V_VAL($$,$1) = TOF($1) + TOF($3); }
+		| expression '-' expression
+			{V_VAL($$,$1) = TOF($1) - TOF($3); }
+		| expression '*' expression
+			{V_VAL($$,$1) = TOF($1) * TOF($3); }
+		| expression '/' expression {
+			if ($3)	V_VAL($$,$1) = TOF($1) / TOF($3);
+			else V_VAL($$,$1) = TOF($3);
+		}
+		| '-' expression %prec UMINUS 
+			{I_VAL($$) = -TOF($2); }
+		| '+' expression %prec UPLUS
+			{V_VAL($$,$2) = TOF($2); }
+		| expression AND_OP expression
+			{I_VAL($$) = VAL_I($1) & VAL_I($3); }
+		| expression OR_OP expression
+			{I_VAL($$) = VAL_I($1) | VAL_I($3); }
+		| expression XOR_OP expression
+			{I_VAL($$) = VAL_I($1) ^ VAL_I($3); }
+		| BIT_NOT_OP expression %prec BIT_NOT_OP
+			{I_VAL($$) = VAL_I($2) ^ (-1); }
+		| expression SHR_OP expression
+			{ unsigned int shift = (1 << VAL_I($3));
+			if (!shift) ALL($$) = ALL($1);
+			else V_VAL($$, $1) =  TOF($1) / shift;}
+		| expression SHL_OP expression
+			{ unsigned int shift = (1 << VAL_I($3));
+			if (!shift) ALL($$) = ALL($1);
+			else V_VAL($$, $1) =  TOF($1) * shift;}
+		| expression EQ_OP expression
+			{B_VAL($$) = TOF($1) == TOF($3); }
+		| expression NEQ_OP expression
+			{B_VAL($$) = TOF($1) != TOF($3); }
+		| expression GE_OP expression
+			{B_VAL($$) = TOF($1) >= TOF($3); }
+		| expression LE_OP expression
+			{B_VAL($$) = TOF($1) <= TOF($3); }
+		| expression '<' expression
+			{B_VAL($$) = TOF($1) < TOF($3); }
+		| expression '>' expression
+			{B_VAL($$) = TOF($1) > TOF($3); }
+		| expression L_AND_OP expression
+			{B_VAL($$) = TOF($1) && TOF($3); }
+		| expression L_OR_OP expression
+			{B_VAL($$) = TOF($1) || TOF($3); }
+		| string_expr STR_EQ_OP string_expr
+			{B_VAL($$) = strcmp($1,$3) == 0; }
+		| string_expr STR_NEQ_OP string_expr
+			{B_VAL($$) = strcmp($1,$3) != 0; }
+		| NOT_OP expression {B_VAL($$) = (TOF($2) ? 0:1); }
+		| L_YES		{B_VAL($$) = 1; }
+		| L_NO		{B_VAL($$) = 0; }
+		| L_ON		{B_VAL($$) = 1; }
+		| L_OFF		{B_VAL($$) = 0; }
+		| L_AUTO	{I_VAL($$) = -1; }
+		| INTCAST '(' expression ')' {I_VAL($$) = TOF($3);}
+		| REALCAST '(' expression ')' {R_VAL($$) = TOF($3);}
+		| STRTOL '(' string_expr ')' {
+			I_VAL($$) = strtol($3,0,0);
+			free($3);
+		}
+		| STRLEN '(' string_expr ')' {
+			I_VAL($$) = strlen($3);
+			free($3);
+		}
+		| STRNCMP '(' string_expr ',' string_expr ',' expression ')' {
+			I_VAL($$) = strncmp($3,$5,$7);
+			free($3); free($5);
+		}
+		| STRPBRK '(' string_expr ',' string_expr ')' {
+			char *s = strpbrk($3,$5);
+			if (s) I_VAL($$) = (int)s - (int)$3;
+			else I_VAL($$) = -1;
+			free($3); free($5);
+		}
+		| STRCHR '(' string_expr ',' string_expr ')' {
+			char *s = strchr($3,$5[0]);
+			if (s) I_VAL($$) = (int)s - (int)$3;
+			else I_VAL($$) = -1;
+			free($3); free($5);
+		}
+		| STRRCHR '(' string_expr ',' string_expr ')' {
+			char *s = strrchr($3,$5[0]);
+			if (s) I_VAL($$) = (int)s - (int)$3;
+			else I_VAL($$) = -1;
+			free($3); free($5);
+		}
+		| STRSTR '(' string_expr ',' string_expr ')' {
+			char *s = strstr($3,$5);
+			if (s) I_VAL($$) = (int)s - (int)$3;
+			else I_VAL($$) = -1;
+			free($3); free($5);
+		}
+		| STRSPN '(' string_expr ',' string_expr ')' {
+			I_VAL($$) = strspn($3,$5);
+			free($3); free($5);
+		}
+		| STRCSPN '(' string_expr ',' string_expr ')' {
+			I_VAL($$) = strcspn($3,$5);
+			free($3); free($5);
+		}
+		| DEFINED '(' STRING ')' {
+			B_VAL($$) = get_config_variable($3) !=0;
+			free($3);
+		}
+		| variable_content {
+			char *s;
+			I_VAL($$) = strtol($1,&s,0);
+			switch (*s) {
+				case '.':  case 'e':  case 'E':
+				/* we assume a real number */
+				R_VAL($$) = strtod($1,0);
+			}
+			free($1);
+		}
+		| '(' expression ')' {ALL($$) = ALL($2);}
+		| STRING {
+			if ( $1[0] && !$1[1] && (EXPRTYPE($1) == TYPE_STRING1) )
+				I_VAL($$) = $1[0];
+			else	yyerror("unrecognized expression '%s'", $1);
+			free($1);
+		}
+		;
+
+variable_content:
+		VARIABLE {
+			char *s = $1;
+			if (get_config_variable(s))
+				s = "1";
+			else if (strncmp("c_",s,2)
+					&& strncmp("u_",s,2)
+					&& strncmp("h_",s,2) ) {
+				s = checked_getenv(s);
+				if (!s) s = "";
+			}
+			else
+				s = "0";
+			S_VAL($$) = strdup(s);
+			free($1);
+		}
+		;
+
+string_expr:	STRING {S_VAL($$) = $1;}
+		| STRCAT '(' strarglist ')' { S_VAL($$) = $3; }
+		| STRSPLIT '(' string_expr ',' expression ',' expression ')' {
+			int i = (int)TOF($5);
+			int len = (int)TOF($7);
+			int slen = strlen($3);
+			if ((i >=0) && (i < slen) && (len > 0)) {
+				if ((i+len) > slen) len = slen - i;
+				$3[i+len] = 0;
+				S_VAL($$) = strdup($3 + i);
+			}
+			else
+				S_VAL($$) = strdup("");
+			free($3);
+		}
+		| STRDEL '(' string_expr ',' expression ',' expression ')' {
+			int i = (int)TOF($5);
+			int len = (int)TOF($7);
+			int slen = strlen($3);
+			char *s = strdup($3);
+			if ((i >=0) && (i < slen) && (len > 0)) {
+				if ((i+len) > slen) s[i] = 0;
+				else memcpy(s+i, s+i+len, slen-i-len+1);
+			}
+			free($3);
+			S_VAL($$) = s;
+		}
+		| SHELL '(' strarglist ')' {
+			IFCLASS(CL_SHELL) {
+				S_VAL($$) = run_shell($3);
+			}
+			else {
+				S_VAL($$) = strdup("");
+				yyerror("not in allowed class to execute SHELL(%s)",$3);
+			}
+			free($3);
+		}
+		| variable_content {ALL($$) = ALL($1);}
+		;
+
+strarglist:	strarglist_item
+		| strarglist ',' strarglist_item {
+			char *s = malloc(strlen($1)+strlen($3)+1);
+			strcpy(s, $1);
+			strcat(s, $3);
+			S_VAL($$) = s;
+			free($1); free($3);
+		}
+		;
+
+strarglist_item: string_expr
+		| '(' expression ')' {
+			char buf[128];
+			if (EXPRTYPE($2) == TYPE_REAL)
+				sprintf(buf, "%g", VAL_R($2));
+			else
+				sprintf(buf, "%d", VAL_I($2));
+			S_VAL($$) = strdup(buf);
+		}
+		;
+
+check_user_var_list:
+		VARIABLE {
+			check_user_var($1);
+			free($1);
+		}
+		| check_user_var_list ',' VARIABLE {
+			check_user_var($3);
+			free($3);
+		}
+		;
+
+	/* x-windows */
+
+x_flags		: x_flag
+		| x_flags x_flag
+		;
+x_flag		: UPDATELINES expression	{ config.X_updatelines = $2; }
+		| UPDATEFREQ expression	{ config.X_updatefreq = $2; }
+		| L_DISPLAY string_expr	{ config.X_display = $2; }
+		| L_TITLE string_expr	{ config.X_title = $2; }
+		| ICON_NAME string_expr	{ config.X_icon_name = $2; }
+		| X_KEYCODE		{ config.X_keycode = 1; }
+		| X_KEYCODE_AUTO	{ config.X_keycode = 2; }
+		| X_BLINKRATE expression	{ config.X_blinkrate = $2; }
+		| X_SHARECMAP		{ config.X_sharecmap = 1; }
+		| X_MITSHM              { config.X_mitshm = 1; }
+		| X_MITSHM bool         { config.X_mitshm = $2; }
+		| X_FONT string_expr		{ config.X_font = $2; }
+		| X_FIXED_ASPECT bool   { config.X_fixed_aspect = $2; }
+		| X_ASPECT_43           { config.X_aspect_43 = 1; }
+		| X_LIN_FILT            { config.X_lin_filt = 1; }
+		| X_BILIN_FILT          { config.X_bilin_filt = 1; }
+		| X_MODE13FACT expression  { config.X_mode13fact = $2; }
+		| X_WINSIZE INTEGER INTEGER
+                   {
+                     config.X_winsize_x = $2;
+                     config.X_winsize_y = $3;
+                   }
+		| X_WINSIZE expression ',' expression
+                   {
+                     config.X_winsize_x = $2;
+                     config.X_winsize_y = $4;
+                   }
+		| X_GAMMA expression  { config.X_gamma = $2; }
+		| VGAEMU_MEMSIZE expression	{ config.vgaemu_memsize = $2; }
+		| VESAMODE INTEGER INTEGER { set_vesamodes($2,$3,0);}
+		| VESAMODE INTEGER INTEGER INTEGER { set_vesamodes($2,$3,$4);}
+		| VESAMODE expression ',' expression { set_vesamodes($2,$4,0);}
+		| VESAMODE expression ',' expression ',' expression
+			{ set_vesamodes($2,$4,$6);}
+		| X_LFB bool            { config.X_lfb = $2; }
+		| X_PM_INTERFACE bool   { config.X_pm_interface = $2; }
+		| X_MGRAB_KEY string_expr { config.X_mgrab_key = $2; }
+		;
+
+dexeflags	: dexeflag
+		| dexeflags dexeflag
+		;
+
+dexeflag	: ALLOWDISK	{ if (!priv_lvl) dexe_forbid_disk = 0; }
+		| L_SECURE	{ dexe_secure = 1; }
+		| FORCEXDOS	{
+			char *env = getenv("DISPLAY");
+			if (env && env[0] && dexe_running) config.X = 1;
+		}
+		| XDOSONLY	{
+			char *env = getenv("DISPLAY");
+			if (env && env[0] && dexe_running) config.X = 1;
+			else if (dexe_running) {
+			  yyerror("this DEXE requires X, giving up");
+			  leavedos(99);
+			}
+		}
+		;
+
+	/* sb emulation */
+ 
+sound_flags	: sound_flag
+		| sound_flags sound_flag
+		;
+sound_flag	: SB_BASE expression	{ config.sb_base = $2; }
+		| SB_DMA expression	{ config.sb_dma = $2; }
+		| SB_IRQ expression	{ config.sb_irq = $2; }
+                | SB_MIXER string_expr       { config.sb_mixer = $2; }
+                | SB_DSP string_expr         { config.sb_dsp = $2; }
+		| MPU_BASE expression	{ config.mpu401_base = $2; }
+		;
+
+	/* video */
+
+video_flags	: video_flag
+		| video_flags video_flag
+		;
+video_flag	: VGA			{ config.cardtype = CARD_VGA; }
+		| MGA			{ config.cardtype = CARD_MDA; }
+		| CGA			{ config.cardtype = CARD_CGA; }
+		| EGA			{ config.cardtype = CARD_EGA; }
+		| NONE			{ config.cardtype = CARD_NONE; }
+		| CHIPSET CHIPSET_TYPE
+		    {
+		    config.chipset = $2;
+                    c_printf("CHIPSET: %d\n", $2);
+		    if ($2==MATROX) config.pci=config.pci_video=1;
+		    }
+		| MEMSIZE expression	{ config.gfxmemsize = $2; }
+		| GRAPHICS
+		    { config.vga = 1;
+		    }
+		| CONSOLE
+		    { config.console_video = 1;
+		    }
+		| FULLREST		{ config.fullrestore = 1; }
+		| PARTREST		{ config.fullrestore = 0; }
+		| VBIOS_FILE string_expr	{ config.vbios_file = $2;
+					  config.mapped_bios = 1;
+					  config.vbios_copy = 0; }
+		| VBIOS_COPY		{ config.vbios_file = NULL;
+					  config.mapped_bios = 1;
+					  config.vbios_copy = 1; }
+		| VBIOS_MMAP		{ config.vbios_file = NULL;
+					  config.mapped_bios = 1;
+					  config.vbios_copy = 1; }
+		| VBIOS_SEG expression
+		   {
+		   config.vbios_seg = $2;
+		   c_printf("CONF: VGA-BIOS-Segment %x\n", $2);
+		   if (($2 != 0xe000) && ($2 != 0xc000))
+		      {
+		      config.vbios_seg = 0xc000;
+		      c_printf("CONF: VGA-BIOS-Segment set to 0xc000\n");
+		      }
+		   }
+		| VBIOS_SIZE_TOK expression
+		   {
+		   config.vbios_size = $2;
+		   c_printf("CONF: VGA-BIOS-Size %x\n", $2);
+		   if (($2 != 0x8000) && ($2 != 0x10000))
+		      {
+		      config.vbios_size = 0x10000;
+		      c_printf("CONF: VGA-BIOS-Size set to 0x10000\n");
+		      }
+		   }
+		| DUALMON		{ config.dualmon = 1; }
+		| FORCE_VT_SWITCH	{ config.force_vt_switch = 1; }
+		| PCI			{ config.pci_video = 1; }
+		| STRING
+		    { yyerror("unrecognized video option '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+	/* terminal */
+
+term_flags	: term_flag
+		| term_flags term_flag
+		;
+term_flag	/* : METHOD method_val	{ config.term_method = $2; } */
+		/* | UPDATELINES INTEGER	{ config.term_updatelines = $2; } */
+                : ESCCHAR expression       { config.term_esc_char = $2; }
+		| UPDATEFREQ expression	{ config.term_updatefreq = $2; }
+		| CHARSET CHARSET_TYPE	{ config.term_charset = $2; }
+		| COLOR color_val	{ config.term_color = $2; }
+		/* | CORNER bool		{ config.term_corner = $2; } */
+		| STRING
+		    { yyerror("unrecognized terminal option '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+color_val	: L_OFF			{ $$ = 0; }
+		| L_ON			{ $$ = 1; }
+		/* | NORMAL		{ $$ = COLOR_NORMAL; } */
+		/* | XTERM			{ $$ = COLOR_XTERM; } */
+		;
+
+/* method_val	: FAST			{ $$ = METHOD_FAST; } */
+/* 		| NCURSES		{ $$ = METHOD_NCURSES; } */
+/* 		; */
+
+	/* debugging */
+
+debug_flags	: debug_flag
+		| debug_flags debug_flag
+		;
+debug_flag	: VIDEO bool		{ d.video = $2; }
+		| L_OFF			{ memset(&d, 0, sizeof(d)); }
+		| SERIAL bool		{ d.serial = $2; }
+		| CONFIG bool		{ if (!d.config) d.config = $2; }
+		| DISK bool		{ d.disk = $2; }
+		| READ bool		{ d.read = $2; }
+		| WRITE bool		{ d.write = $2; }
+		| KEYB bool		{ d.keyb = $2; }
+		| KEYBOARD bool		{ d.keyb = $2; }
+		| PRINTER bool		{ d.printer = $2; }
+		| IO bool		{ d.io = $2; }
+		| PORT bool 		{ d.io = $2; }
+		| WARNING bool		{ d.warning = $2; }
+		| GENERAL bool		{ d.general = $2; }
+		| L_XMS bool		{ d.xms = $2; }
+		| L_DPMI bool		{ d.dpmi = $2; }
+		| MOUSE bool		{ d.mouse = $2; }
+		| HARDWARE bool		{ d.hardware = $2; }
+		| L_IPC bool		{ d.IPC = $2; }
+		| L_EMS bool		{ d.EMS = $2; }
+		| NETWORK bool		{ d.network = $2; }
+		| L_X bool		{ d.X = $2; }
+		| SOUND	bool		{ d.sound = $2; }
+		| STRING
+		    { yyerror("unrecognized debug flag '%s'", $1); free($1); }
+		| error
+		;
+
+	/* mouse */
+
+mouse_flags	: mouse_flag
+		| mouse_flags mouse_flag
+		;
+mouse_flag	: DEVICE string_expr		{ strcpy(mptr->dev, $2); free($2); }
+		| INTERNALDRIVER	{ mptr->intdrv = TRUE; }
+		| EMULATE3BUTTONS	{ mptr->emulate3buttons = TRUE; }
+		| BAUDRATE expression	{ mptr->baudRate = $2; }
+		| CLEARDTR
+		    { if (mptr->type == MOUSE_MOUSESYSTEMS)
+			 mptr->cleardtr = TRUE;
+		      else
+			 yyerror("option CLEARDTR is only valid for MicroSystems-Mice");
+		    }
+		| MICROSOFT
+		  {
+		  mptr->type = MOUSE_MICROSOFT;
+		  mptr->flags = CS7 | CREAD | CLOCAL | HUPCL;
+		  }
+		| MS3BUTTON
+		  {
+		  mptr->type = MOUSE_MS3BUTTON;
+		  mptr->flags = CS7 | CREAD | CLOCAL | HUPCL;
+		  }
+		| MOUSESYSTEMS
+		  {
+		  mptr->type = MOUSE_MOUSESYSTEMS;
+		  mptr->flags = CS8 | CREAD | CLOCAL | HUPCL;
+/* is cstopb needed?  mptr->flags = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL; */
+		  }
+		| MMSERIES
+		  {
+		  mptr->type = MOUSE_MMSERIES;
+		  mptr->flags = CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL;
+		  }
+		| LOGITECH
+		  {
+		  mptr->type = MOUSE_LOGITECH;
+		  mptr->flags = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL;
+		  }
+		| PS2
+		  {
+		  mptr->type = MOUSE_PS2;
+		  mptr->flags = 0;
+		  }
+		| MOUSEMAN
+		  {
+		  mptr->type = MOUSE_MOUSEMAN;
+		  mptr->flags = CS7 | CREAD | CLOCAL | HUPCL;
+		  }
+		| HITACHI
+		  {
+		  mptr->type = MOUSE_HITACHI;
+		  mptr->flags = CS8 | CREAD | CLOCAL | HUPCL;
+		  }
+		| BUSMOUSE
+		  {
+		  mptr->type = MOUSE_BUSMOUSE;
+		  mptr->flags = 0;
+		  }
+		| STRING
+		    { yyerror("unrecognized mouse flag '%s'", $1); free($1); }
+		| error
+		;
+
+	/* keyboard */
+
+keyboard_flags	: keyboard_flag
+		| keyboard_flags keyboard_flag
+		;
+keyboard_flag	: LAYOUT KEYB_LAYOUT	{ keyb_layout($2); }
+		| LAYOUT KEYB_LAYOUT {keyb_layout($2);} '{' keyboard_mods '}'
+		| LAYOUT L_NO		{ keyb_layout(KEYB_NO); }
+		| LAYOUT L_AUTO		{ keyb_layout(-1); }
+		| RAWKEYBOARD bool	{ config.console_keyb = $2; }
+		| KEYBINT bool		{ config.keybint = $2; }
+		| STRING
+		    { yyerror("unrecognized keyboard flag '%s'", $1);
+		      free($1);}
+		| error
+		;
+
+keyboard_mods	: keyboard_mod
+		| keyboard_mods keyboard_mod
+		;
+
+keyboard_mod	: expression '=' { keyb_mod(' ', $1); } keyboard_modvals
+		| SHIFT expression '=' { keyb_mod('S', $2); } keyboard_modvals
+		| ALT expression '=' { keyb_mod('A', $2); } keyboard_modvals
+		| NUMPAD expression '=' { keyb_mod('N', $2); } keyboard_modvals
+		;
+
+keyboard_modvals: keyboard_modval
+		| keyboard_modvals ',' keyboard_modval
+		;
+
+keyboard_modval : INTEGER { keyb_mod(0, $1); }
+		| '(' expression ')' { keyb_mod(0, $2); }
+		| DGRAVE { keyb_mod(0, DEAD_GRAVE); }
+		| DACUTE { keyb_mod(0, DEAD_ACUTE); }
+		| DCIRCUM { keyb_mod(0, DEAD_CIRCUMFLEX); }
+		| DTILDE { keyb_mod(0, DEAD_TILDE); }
+		| DBREVE { keyb_mod(0, DEAD_BREVE); }
+		| DABOVED { keyb_mod(0, DEAD_ABOVEDOT); }
+		| DDIARES { keyb_mod(0, DEAD_DIAERESIS); }
+		| DABOVER { keyb_mod(0, DEAD_ABOVERING); }
+		| DDACUTE { keyb_mod(0, DEAD_DOUBLEACUTE); }
+		| DCEDILLA { keyb_mod(0, DEAD_CEDILLA); }
+		| DIOTA { keyb_mod(0,DEAD_IOTA); }
+		| DOGONEK { keyb_mod(0,DEAD_OGONEK); }
+		| DCARON { keyb_mod(0,DEAD_CARON); }
+		| STRING {
+			char *p = $1;
+			while (*p) keyb_mod(0, *p++);
+			free($1);
+		}
+		;
+
+	/* lock files */
+
+ttylocks_flags	: ttylocks_flag
+		| ttylocks_flags ttylocks_flag
+		;
+ttylocks_flag	: DIRECTORY string_expr	{ config.tty_lockdir = $2; }
+		| NAMESTUB string_expr	{ config.tty_lockfile = $2; }
+		| BINARY		{ config.tty_lockbinary = TRUE; }
+		| STRING
+		    { yyerror("unrecognized ttylocks flag '%s'", $1); free($1); }
+		| error
+		;
+
+	/* serial ports */
+
+serial_flags	: serial_flag
+		| serial_flags serial_flag
+		;
+serial_flag	: DEVICE string_expr		{ strcpy(sptr->dev, $2);
+					  if (!strcmp("/dev/mouse",sptr->dev)) sptr->mouse=1;
+					  free($2); }
+		| COM expression		{ sptr->real_comport = $2;
+					  com_port_used[$2] = 1; }
+		| BASE expression		{ sptr->base_port = $2; }
+		| IRQ expression		{ sptr->interrupt = $2; }
+		| INTERRUPT expression	{ sptr->interrupt = $2; }
+		| MOUSE			{ sptr->mouse = 1; }
+		| STRING
+		    { yyerror("unrecognized serial flag '%s'", $1); free($1); }
+		| error
+		;
+
+	/* printer */
+
+printer_flags	: printer_flag
+		| printer_flags printer_flag
+		;
+printer_flag	: COMMAND string_expr	{ pptr->prtcmd = $2; }
+		| TIMEOUT expression	{ pptr->delay = $2; }
+		| OPTIONS string_expr	{ pptr->prtopt = $2; }
+		| L_FILE string_expr		{ pptr->dev = $2; }
+		| BASE expression		{ pptr->base_port = $2; }
+		| STRING
+		    { yyerror("unrecognized printer flag %s", $1); free($1); }
+		| error
+		;
+
+	/* disks */
+
+optbootfile	: BOOTFILE string_expr
+		  {
+                  if (priv_lvl)
+                    yyerror("Can not use BOOTFILE in the user config file\n");
+		  if (dptr->boot_name != NULL)
+		    yyerror("Two names for a boot-image file or device given.");
+		  dptr->boot_name = $2;
+                  }
+		| /* empty */
+		;
+
+disk_flags	: disk_flag
+		| disk_flags disk_flag
+		;
+disk_flag	: READONLY		{ dptr->wantrdonly = 1; }
+		| THREEINCH	{ dptr->default_cmos = THREE_INCH_FLOPPY; }
+		| ATAPI		{ dptr->default_cmos = ATAPI_FLOPPY; }
+		| FIVEINCH	{ dptr->default_cmos = FIVE_INCH_FLOPPY; }
+		| DISKCYL4096	{ dptr->diskcyl4096 = 1; }
+		| SECTORS expression	{ dptr->sectors = $2; }
+		| CYLINDERS expression	{ dptr->tracks = $2; }
+		| TRACKS expression	{ dptr->tracks = $2; }
+		| HEADS expression		{ dptr->heads = $2; }
+		| OFFSET expression	{ dptr->header = $2; }
+		| DEVICE string_expr optbootfile
+		  {
+                  if (priv_lvl)
+                    yyerror("Can not use DISK/DEVICE in the user config file\n");
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a disk-image file or device given.");
+		  dptr->dev_name = $2;
+		  }
+		| L_FILE string_expr
+		  {
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a disk-image file or device given.");
+		  dptr->dev_name = $2;
+		  }
+		| HDIMAGE string_expr
+		  {
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a harddisk-image file given.");
+		  dptr->type = IMAGE;
+		  dptr->header = HEADER_SIZE;
+		  dptr->dev_name = $2;
+		  }
+		| WHOLEDISK STRING optbootfile
+		  {
+                  if (priv_lvl)
+                    yyerror("Can not use DISK/WHOLEDISK in the user config file\n");
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a harddisk given.");
+		  dptr->type = HDISK;
+		  dptr->dev_name = $2;
+		  }
+		| L_FLOPPY string_expr
+		  {
+                  if (priv_lvl)
+                    yyerror("Can not use DISK/FLOPPY in the user config file\n");
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a floppy-device given.");
+		  dptr->type = FLOPPY;
+		  dptr->dev_name = $2;
+		  }
+		| L_PARTITION string_expr INTEGER optbootfile
+		  {
+                  yywarn("{ partition \"%s\" %d } the"
+			 " token '%d' is ignored and can be removed.",
+			 $2,$3,$3);
+		  do_part($2);
+		  }
+		| L_PARTITION string_expr optbootfile
+		  { do_part($2); }
+		| DIRECTORY string_expr
+		  {
+		  if (dptr->dev_name != NULL)
+		    yyerror("Two names for a directory given.");
+		  dptr->type = DIR_TYPE;
+		  dptr->dev_name = $2;
+		  }
+		| STRING
+		    { yyerror("unrecognized disk flag '%s'\n", $1); free($1); }
+		| error
+		;
+
+	/* i/o ports */
+
+port_flags	: port_flag
+		| port_flags port_flag
+		;
+port_flag	: INTEGER
+	           {
+	           allow_io($1, 1, ports_permission, ports_ormask,
+	                    ports_andmask,portspeed?1:0, (char*)dev_name);
+		   if (portspeed) portspeed++;
+	           }
+		| '(' expression ')'
+	           {
+	           allow_io($2, 1, ports_permission, ports_ormask,
+	                    ports_andmask,portspeed?1:0, (char*)dev_name);
+		   if (portspeed) portspeed++;
+	           }
+		| RANGE INTEGER INTEGER
+		   {
+		   if (portspeed > 1) portspeed=0;
+		   c_printf("CONF: range of I/O ports 0x%04x-0x%04x\n",
+			    (unsigned short)$2, (unsigned short)$3);
+		   allow_io($2, $3 - $2 + 1, ports_permission, ports_ormask,
+			    ports_andmask, portspeed?1:0, (char*)dev_name);
+		   portspeed=0;
+		   strcpy(dev_name,"");
+		   }
+		| RANGE expression ',' expression
+		   {
+		   if (portspeed > 1) portspeed=0;
+		   c_printf("CONF: range of I/O ports 0x%04x-0x%04x\n",
+			    (unsigned short)$2, (unsigned short)$4);
+		   allow_io($2, $4 - $2 + 1, ports_permission, ports_ormask,
+			    ports_andmask, portspeed?1:0, (char*)dev_name);
+		   portspeed=0;
+		   strcpy(dev_name,"");
+		   }
+		| RDONLY		{ ports_permission = IO_READ; }
+		| WRONLY		{ ports_permission = IO_WRITE; }
+		| RDWR			{ ports_permission = IO_RDWR; }
+		| ORMASK expression	{ ports_ormask = $2; }
+		| ANDMASK expression	{ ports_andmask = $2; }
+                | FAST	                { portspeed = 1; }
+                | DEVICE string_expr         { strcpy(dev_name,$2); free($2); } 
+		| STRING
+		    { yyerror("unrecognized port command '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+trace_port_flags	: trace_port_flag
+		| trace_port_flags trace_port_flag
+		;
+trace_port_flag	: INTEGER 
+			{ register_port_traceing($1, $1); }
+		| '(' expression ')'
+			{ register_port_traceing($2, $2); }
+		| RANGE INTEGER INTEGER
+			{ register_port_traceing($2, $3); }
+		| RANGE expression ',' expression
+			{ register_port_traceing($2, $4); }
+		| CLEAR { clear_port_traceing(); }
+		| STRING
+		    { yyerror("unrecognized port trace command '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+	/* IRQ definition for Silly Interrupt Generator */
+
+sillyint_flags	: sillyint_flag
+		| sillyint_flags sillyint_flag
+		;
+sillyint_flag	: INTEGER { set_irq_value(1, $1); }
+		| '(' expression ')' { set_irq_value(1, $2); }
+		| USE_SIGIO expression { set_irq_value(0x10001, $2); }
+		| RANGE INTEGER INTEGER { set_irq_range(1, $2, $3); }
+		| RANGE expression ',' expression { set_irq_range(1, $2, $4); }
+		| USE_SIGIO RANGE INTEGER INTEGER { set_irq_range(0x10001, $3, $4); }
+		| USE_SIGIO RANGE expression ',' expression { set_irq_range(0x10001, $3, $5); }
+		| STRING
+		    { yyerror("unrecognized irqpassing command '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+	/* EMS definitions  */
+
+ems_flags	: ems_flag
+		| ems_flags ems_flag
+		;
+ems_flag	: INTEGER
+	           {
+		     config.ems_size = $1;
+		     if ($1 > 0) c_printf("CONF: %dk bytes EMS memory\n", $1);
+	           }
+		| '(' expression ')'
+	           {
+		     config.ems_size = $2;
+		     if ($2 > 0) c_printf("CONF: %dk bytes EMS memory\n", $2);
+	           }
+		| EMS_SIZE expression
+		   {
+		     config.ems_size = $2;
+		     if ($2 > 0) c_printf("CONF: %dk bytes EMS memory\n", $2);
+		   }
+		| EMS_FRAME expression
+		   {
+/* is there a technical reason why the EMS frame can't be at 0xC0000 or
+   0xA0000 if there's space? */
+#if 0
+		     if ( (($2 & 0xfc00)>=0xc800) && (($2 & 0xfc00)<=0xe000) ) {
+		       config.ems_frame = $2 & 0xfc00;
+		       c_printf("CONF: EMS-frame = 0x%04x\n", config.ems_frame);
+		     }
+		     else yyerror("wrong EMS-frame: 0x%04x", $2);
+#endif
+	             config.ems_frame = $2 & 0xfc00;
+		     c_printf("CONF: EMS-frame = 0x%04x\n", config.ems_frame);
+		   }
+		| STRING
+		    { yyerror("unrecognized ems command '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+	/* memory areas to spare for hardware (adapter) ram */
+
+hardware_ram_flags : hardware_ram_flag
+		| hardware_ram_flags hardware_ram_flag
+		;
+hardware_ram_flag : INTEGER
+	           {
+                     if (!set_hardware_ram($1)) {
+                       yyerror("wrong hardware ram address : 0x%05x", $1);
+                     }
+	           }
+		| '(' expression ')'
+	           {
+                     if (!set_hardware_ram($2)) {
+                       yyerror("wrong hardware ram address : 0x%05x", $2);
+                     }
+	           }
+		| RANGE INTEGER INTEGER
+		   {
+                     int i;
+                     for (i=$2; i<= $3; i+=0x1000) {
+                       if (set_hardware_ram(i))
+	                   c_printf("CONF: hardware ram page at 0x%05x\n", i);
+                       else {
+                         yyerror("wrong hardware ram address : 0x%05x", i);
+                         break;
+                       }
+                     }
+		   }
+		| RANGE expression ',' expression
+		   {
+                     int i;
+                     for (i=$2; i<= $4; i+=0x1000) {
+                       if (set_hardware_ram(i))
+	                   c_printf("CONF: hardware ram page at 0x%05x\n", i);
+                       else {
+                         yyerror("wrong hardware ram address : 0x%05x", i);
+                         break;
+                       }
+                     }
+		   }
+		| STRING
+		    { yyerror("unrecognized hardware ram command '%s'", $1);
+		      free($1); }
+		| error
+		;
+
+	/* booleans */
+
+bool:		expression
+		;
+
+floppy_bool:	expression
+		;
+
+mem_bool:	expression {
+			if ($1 == 1) {
+				yyerror("got 'on', expected 'off' or an integer");
+			}
+		}
+		;
+
+irq_bool:	expression {
+			if ( $1 && (($1 < 2) || ($1 > 15)) ) {
+				yyerror("got '%d', expected 'off' or an integer 2..15", $1);
+			} 
+		}
+		;
+
+	/* speaker values */
+
+speaker		: L_OFF		{ $$ = SPKR_OFF; }
+		| NATIVE	{ $$ = SPKR_NATIVE; }
+		| EMULATED	{ $$ = SPKR_EMULATED; }
+		| STRING        { yyerror("got '%s', expected 'emulated' or 'native'", $1);
+				  free($1); }
+		| error         { yyerror("expected 'emulated' or 'native'"); }
+		;
+
+%%
+
+
+	/* features */
+
+static void handle_features(int which, int value)
+{
+  if ((which < 0)
+	|| (which >= (sizeof(config.features) / sizeof(config.features[0])))) {
+    c_printf("CONF: wrong feature number %d\n", which);
+    return;
+  }
+  config.features[which] = value;
+  c_printf("CONF: feature %d set to %d\n", which, value);
+}
+
+	/* mouse */
+
+static void start_mouse(void)
+{
+  if (c_mouse >= MAX_MOUSE)
+    mptr = &nullmouse;
+  else {
+    mptr = &mice[c_mouse];
+    mptr->fd = -1;
+  }
+}
+
+static void stop_mouse(void)
+{
+  if (c_mouse >= MAX_MOUSE) {
+    c_printf("MOUSE: too many mice, ignoring %s\n", mptr->dev);
+    return;
+  }
+  c_mouse++;
+  config.num_mice = c_mouse;
+  c_printf("MOUSE: %s type %x using internaldriver: %s, emulate3buttons: %s baudrate: %d\n", 
+        mptr->dev, mptr->type, mptr->intdrv ? "yes" : "no", mptr->emulate3buttons ? "yes" : "no", mptr->baudRate);
+}
+
+	/* debug */
+
+static void start_ports(void)
+{
+  if (priv_lvl)
+    yyerror("Can not change port privileges in user config file");
+  ports_permission = IO_RDWR;
+  ports_ormask = 0;
+  ports_andmask = 0xFFFF;
+}
+
+	/* debug */
+
+static void start_debug(void)
+{
+  int flag = 0;                 /* Default is no debugging output at all */
+
+  d.video = flag;               /* For all options */
+  d.serial = flag;
+#if 0
+  d.config = flag;
+#endif
+  d.disk = flag;
+  d.read = flag;
+  d.write = flag;
+  d.keyb = flag;
+  d.printer = flag;
+  d.io = flag;
+  d.warning = flag;
+  d.general = flag;
+  d.xms = flag;
+  d.dpmi = flag;
+  d.mouse = flag;
+  d.hardware = flag;
+  d.IPC = flag;
+  d.EMS = flag;
+  d.network = flag;
+  d.sound = flag;
+}
+
+	/* video */
+
+static void start_video(void)
+{
+  config.vbios_file = NULL;
+  config.vbios_copy = 0;
+  config.vbios_seg  = 0xc000;
+  config.vbios_size = 0x10000;
+  config.console_video = 0;
+  config.cardtype = CARD_VGA;
+  config.chipset = PLAINVGA;
+  config.mapped_bios = 0;
+  config.graphics = 0;
+  config.vga = 0;
+  config.gfxmemsize = 256;
+  config.fullrestore = 0;
+  config.dualmon = 0;
+  config.force_vt_switch = 0;
+}
+
+static void stop_video(void)
+{
+  if ((config.cardtype != CARD_VGA) || !config.console_video) {
+    config.graphics = 0;
+    config.vga = 0;
+  }
+
+  if (config.vga) {
+    if (config.mem_size > 640)
+      config.mem_size = 640;
+    config.mapped_bios = 1;
+    config.console_video = 1;
+  }
+}
+
+	/* vesa modes */
+static void set_vesamodes(int width, int height, int color_bits)
+{
+  vesamode_type *vmt = malloc(sizeof *vmt);
+  if(vmt != NULL) {
+    vmt->width = width;
+    vmt->height = height;
+    vmt->color_bits = color_bits;
+    vmt->next = config.vesamode_list;
+    config.vesamode_list = vmt;
+  }
+}
+
+        /* tty lock files */
+static void start_ttylocks(void)
+{
+  if (priv_lvl)
+    yyerror("Can not change lock file settings in user config file");
+}
+
+
+static void stop_ttylocks(void)
+{
+  c_printf("SER: directory %s namestub %s binary %s\n", config.tty_lockdir,
+	   config.tty_lockfile,(config.tty_lockbinary?"Yes":"No"));
+}
+
+	/* serial */
+
+static void start_serial(void)
+{
+  if (c_ser >= MAX_SER)
+    sptr = &nullser;
+  else {
+    /* The defaults for interrupt, base_port, real_comport and dev are 
+    ** automatically filled in inside the do_ser_init routine of serial.c
+    */
+    sptr = &com[c_ser];
+    sptr->dev[0] = 0;
+    sptr->interrupt = 0; 
+    sptr->base_port = 0;
+    sptr->real_comport = 0;
+    sptr->fd = -1;
+    sptr->mouse = 0;
+  }
+}
+
+
+static void stop_serial(void)
+{
+  if (c_ser >= MAX_SER) {
+    c_printf("SER: too many ports, ignoring %s\n", sptr->dev);
+    return;
+  }
+  c_ser++;
+  config.num_ser = c_ser;
+  c_printf("SER: %s port %x int %x\n", sptr->dev, sptr->base_port,
+	   sptr->interrupt);
+}
+
+	/* keyboard */
+
+static int keyboard_statement_already = 0;
+
+static void start_keyboard(void)
+{
+  keyb_layout(KEYB_USER); /* NOTE: the default has changed, --Hans, 971204 */
+  config.console_keyb = 0;
+  config.keybint = 0;
+  keyboard_statement_already = 1;
+}
+
+	/* terminal */
+
+static void start_terminal(void)
+{
+   /* config.term_method = METHOD_FAST; */
+   /* config.term_updatelines = 25; */
+  config.term_updatefreq = 4;
+#if 0 /* we don't preset it here, as it now is set by its own statement
+       * and it's already preset in config_defaults() (config.c).
+       *       --Hans
+       */
+  config.term_charset = CHARSET_LATIN;
+#endif
+  config.term_color = 1;
+   config.term_esc_char = 30;	       /* Ctrl-^ */
+   /* config.term_corner = 1; */
+}
+
+static void stop_terminal(void)
+{
+  if (config.term_updatefreq > 100) {
+    yywarn("terminal updatefreq too large (too slow)!");
+    config.term_updatefreq = 100;
+  } 
+}
+
+	/* printer */
+
+static void start_printer(void)
+{
+  if (c_printers >= NUM_PRINTERS)
+    pptr = &nullptr;
+  else {
+    pptr = &lpt[c_printers];
+    /* this causes crashes ?? */
+#if 0
+    pptr->prtcmd = strdup("lpr");
+    pptr->prtopt = strdup("%s");
+#else
+    pptr->prtcmd = NULL;
+    pptr->prtopt = NULL;
+#endif
+    pptr->dev = NULL;
+    pptr->file = NULL;
+    pptr->remaining = -1;
+    pptr->delay = 10;
+  }
+}
+
+static void stop_printer(void)
+{
+  c_printf("CONF(LPT%d) f: %s   c: %s  o: %s  t: %d  port: %x\n",
+	   c_printers, pptr->dev, pptr->prtcmd, pptr->prtopt,
+           pptr->delay, pptr->base_port);
+  c_printers++;
+  config.num_lpt = c_printers;
+}
+
+	/* disk */
+
+static void start_bootdisk(void)
+{
+  if (priv_lvl)
+    yyerror("Can not change disk settings in user config file");
+
+  if (config.bootdisk)           /* Already a bootdisk configured ? */
+    yyerror("There is already a bootdisk configured");
+      
+  dptr = &bootdisk;              /* set pointer do bootdisk-struct */
+      
+  dptr->diskcyl4096 = 0;
+  dptr->sectors = 0;             /* setup default-values           */
+  dptr->heads   = 0;
+  dptr->tracks  = 0;
+  dptr->type    = FLOPPY;
+  dptr->default_cmos = THREE_INCH_FLOPPY;
+  dptr->timeout = 0;
+  dptr->dev_name = NULL;              /* default-values */
+  dptr->boot_name = NULL;
+  dptr->wantrdonly = 0;
+  dptr->header = 0;
+}
+
+static void start_floppy(void)
+{
+  if (priv_lvl)
+    yyerror("Can not change disk settings in user config file");
+
+  if (c_fdisks >= MAX_FDISKS)
+    {
+    yyerror("There are too many floppy disks defined");
+    dptr = &nulldisk;          /* Dummy-Entry to avoid core-dumps */
+    }
+  else
+    dptr = &disktab[c_fdisks];
+
+  dptr->sectors = 0;             /* setup default values */
+  dptr->heads   = 0;
+  dptr->tracks  = 0;
+  dptr->type    = FLOPPY;
+  dptr->default_cmos = THREE_INCH_FLOPPY;
+  dptr->timeout = 0;
+  dptr->dev_name = NULL;              /* default-values */
+  dptr->boot_name = NULL;
+  dptr->wantrdonly = 0;
+  dptr->header = 0;
+}
+
+static void start_disk(void)
+{
+  if (c_hdisks >= MAX_HDISKS) 
+    {
+    yyerror("There are too many hard disks defined");
+    dptr = &nulldisk;          /* Dummy-Entry to avoid core-dumps */
+    }
+  else
+    dptr = &hdisktab[c_hdisks];
+      
+  dptr->type    =  NODISK;
+  dptr->sectors = -1;
+  dptr->heads   = -1;
+  dptr->tracks  = -1;
+  dptr->timeout = 0;
+  dptr->dev_name = NULL;              /* default-values */
+  dptr->boot_name = NULL;
+  dptr->wantrdonly = 0;
+  dptr->header = 0;
+  dptr->dexeflags = 0;
+}
+
+static void do_part(char *dev)
+{
+  if (priv_lvl)
+    yyerror("Can not use DISK/PARTITION in the user config file\n");
+
+  if (dptr->dev_name != NULL)
+    yyerror("Two names for a partition given.");
+  dptr->type = PARTITION;
+  dptr->dev_name = dev;
+#ifdef __linux__
+  dptr->part_info.number = atoi(dptr->dev_name+8);
+#endif
+  if (dptr->part_info.number == 0) 
+    yyerror("%s must be a PARTITION, can't find number suffix!\n",
+   	    dptr->dev_name);
+}
+
+static void stop_disk(int token)
+{
+#ifdef __linux__
+  FILE   *f;
+  struct mntent *mtab;
+#endif
+  int    mounted_rw;
+
+  if (dexe_running && dexe_forbid_disk)
+    return;
+  if (dptr == &nulldisk)              /* is there any disk? */
+    return;                           /* no, nothing to do */
+
+  if (!dptr->dev_name)                /* Is there a file/device-name? */
+    yyerror("disk: no device/file-name given!");
+  else                                /* check the file/device for existance */
+    {
+      struct stat file_status;        /* date for checking that file */
+
+      c_printf("device: %s ", dptr->dev_name);
+      if (stat(dptr->dev_name,&file_status) != 0) /* Does this file exist? */
+	 yyerror("Disk-device/file %s doesn't exist.",dptr->dev_name);
+    }
+
+  if (dptr->type == NODISK)    /* Is it one of bootdisk, floppy, harddisk ? */
+    yyerror("disk: no device/file-name given!"); /* No, error */
+  else
+    c_printf("type %d ", dptr->type);
+
+  if (dptr->type == PARTITION) {
+    c_printf("partition# %d ", dptr->part_info.number);
+#ifdef __linux__
+    mtab = NULL;
+    if ((f = setmntent(MOUNTED, "r")) != NULL) {
+      while ((mtab = getmntent(f)))
+        if (!strcmp(dptr->dev_name, mtab->mnt_fsname)) break;
+      endmntent(f);
+    }
+    if (mtab) {
+      mounted_rw = ( hasmntopt(mtab, MNTOPT_RW) != NULL );
+      if (mounted_rw && !dptr->wantrdonly) 
+        yyerror("\n\nYou specified '%s' for read-write Direct Partition Access,"
+                "\nit is currently mounted read-write on '%s' !!!\n",
+                dptr->dev_name, mtab->mnt_dir);
+      else if (mounted_rw) 
+        yywarn("You specified '%s' for read-only Direct Partition Access,"
+               "\n         it is currently mounted read-write on '%s'.\n",
+               dptr->dev_name, mtab->mnt_dir);
+      else if (!dptr->wantrdonly) 
+        yywarn("You specified '%s' for read-write Direct Partition Access,"
+               "\n         it is currently mounted read-only on '%s'.\n",
+               dptr->dev_name, mtab->mnt_dir);
+    }
+#endif
+  }
+
+  if (dptr->header)
+    c_printf("header_size: %ld ", (long) dptr->header);
+
+  c_printf("h: %d  s: %d   t: %d", dptr->heads, dptr->sectors,
+	   dptr->tracks);
+
+  if (token == BOOTDISK) {
+    config.bootdisk = 1;
+    use_bootdisk = 1;
+    c_printf(" bootdisk\n");
+  }
+  else if (token == L_FLOPPY) {
+    c_printf(" floppy %c:\n", 'A'+c_fdisks);
+    c_fdisks++;
+    config.fdisks = c_fdisks;
+  }
+  else {
+    c_printf(" drive %c:\n", 'C'+c_hdisks);
+    c_hdisks++;
+    config.hdisks = c_hdisks;
+  }
+}
+
+	/* keyboard */
+
+void keyb_layout(int layout)
+{
+  struct keytable_entry *kt = keytable_list;
+  if (layout == -1) {
+    layout = setup_default_keytable();
+    if(layout < 0) layout = KEYB_US;
+  }
+  while (kt->name) {
+    if (kt->keyboard == layout) {
+      c_printf("CONF: Keyboard-layout %s\n", kt->name);
+      config.keytable = kt;
+      return;
+    }
+    kt++;
+  }
+  c_printf("CONF: ERROR -- Keyboard has incorrect number!!!\n");
+}
+
+static void keytable_start(int layout)
+{
+  static struct keytable_entry *saved_kt = 0;
+  if (layout == -1) {
+    if (keyboard_statement_already) {
+      if (config.keytable != saved_kt) {
+        yywarn("keytable changed to %s table, but previously was defined %s\n",
+                config.keytable->name, saved_kt->name);
+      }
+    }
+  }
+  else {
+    saved_kt = config.keytable;
+    keyb_layout(layout);
+  }
+}
+
+static void keytable_stop(void)
+{
+  keytable_start(-1);
+}
+
+static void keyb_mod(int wich, int keynum)
+{
+  static unsigned char *table = 0;
+  static int count = 0;
+  static int in_altmap = 0;
+
+  switch (wich) {
+    case ' ': {
+      in_altmap = 0;
+      switch (keynum & 0x300) {
+        case 0: table = config.keytable->key_map;
+        	count=config.keytable->sizemap;
+        	break;
+        case 0x100: table = config.keytable->shift_map;
+        	count=config.keytable->sizemap;
+        	break;
+        case 0x200: table = config.keytable->alt_map;
+        	count=config.keytable->sizemap;
+        	in_altmap = 1;
+        	break;
+        case 0x300: table = config.keytable->num_table;
+        	count=config.keytable->sizepad;
+        	break;
+      }
+      break;
+    }
+    case 'S': table = config.keytable->shift_map;
+    	count=config.keytable->sizemap;
+	in_altmap = 0;
+    	break;
+    case 'A': table = config.keytable->alt_map;
+    	count=config.keytable->sizemap;
+    	in_altmap = 1;
+    	break;
+    case 'N': table = config.keytable->num_table;
+    	count=config.keytable->sizepad;
+	in_altmap = 0;
+    	break;
+  }
+
+  keynum &= 0xff;
+  if (wich) {
+    if (keynum >= count) return;
+    table += keynum;
+    count -= keynum;
+    return;
+  }
+  if (count > 0) {
+    *table++ = keynum;
+    if (in_altmap && keynum)
+      config.keytable->flags |= KT_USES_ALTMAP;
+    count--;
+  }
+}
+
+
+static void dump_keytable_part(FILE *f, unsigned char *map, int size)
+{
+  int i, in_string=0, is_deadkey;
+  unsigned char c, *cc, comma=' ', buf[16];
+  static unsigned char dead_key_list[] = {FULL_DEADKEY_LIST, 0};
+  static char *dead_key_names[] = {
+    "dgrave", "dacute", "dcircum", "dtilde", "dbreve", "daboved", "ddiares",
+    "dabover", "ddacute", "dcedilla", "diota", "dogonek", "dcaron"
+  };
+
+  size--;
+  for (i=0; i<=size; i++) {
+    c = map[i];
+    if (!(i & 15)) fprintf(f,"    ");
+    is_deadkey = c ? (int)strchr(dead_key_list, c) : 0;
+    if (!is_deadkey && isprint(c) && !strchr("\\\"\'`", c)) {
+      if (in_string) fputc(c,f);
+      else {
+        fprintf(f, "%c\"%c", comma, c);
+        in_string = 1;
+      }
+    }
+    else {
+      if (is_deadkey) cc = dead_key_names[is_deadkey - (int)(&dead_key_list)];
+      else {
+        sprintf(buf, "%d", c);
+        cc = buf;
+      }
+      if (!in_string) fprintf(f, "%c%s", comma, cc);
+      else {
+        fprintf(f, "\",%s", cc);
+        in_string = 0;
+      }
+    }
+    if ((i & 15) == 15) {
+      if (in_string) fputc('"', f);
+      if (i < size) fputc(',', f);
+      fputc('\n', f);
+      in_string = 0;
+      comma = ' ';
+    }
+    else comma = ',';
+  }
+  if (in_string) fputc('"', f);
+  fputc('\n', f);
+}
+
+void dump_keytable(FILE *f, struct keytable_entry *kt)
+{
+    fprintf(f, "keytable %s {\n", kt->name);
+    fprintf(f, "  0=\n");
+    dump_keytable_part(f, kt->key_map, kt->sizemap);
+    fprintf(f, "  shift 0=\n");
+    dump_keytable_part(f, kt->shift_map, kt->sizemap);
+    fprintf(f, "  alt 0=\n");
+    dump_keytable_part(f, kt->alt_map, kt->sizemap);
+    fprintf(f, "  numpad 0=\n");
+    dump_keytable_part(f, kt->num_table, kt->sizepad-1);
+    fprintf(f, "}\n\n\n");
+}
+
+static void dump_keytables_to_file(char *name)
+{
+  PRIV_SAVE_AREA
+  FILE * f;
+  struct keytable_entry *kt = keytable_list;
+
+  enter_priv_off();
+  f = fopen(name, "w");
+  leave_priv_setting();
+  if (!f) {
+    error("cannot create keytable file %s\n", name);
+    exit(1);
+  }
+  
+  while (kt->name) {
+    dump_keytable(f, kt);
+    kt++;
+  }
+  fclose(f);
+  exit(0);
+}
+
+static int set_hardware_ram(int addr)
+{
+  if ((addr>=0xc800) && (addr<0xf000))   addr *= 0x10;
+  if ((addr<0xc8000) || (addr>=0xf0000)) return 0;
+  memcheck_reserve('h', addr, 4096);
+  config.must_spare_hardware_ram=1;
+  config.hardware_pages[(addr-0xc8000) >> 12]=1;
+  return 1;
+}
+
+
+static void set_irq_value(int bits, int i1)
+{
+  if ((i1>2) && (i1<=15)) {
+    config.sillyint |= (bits << i1);
+    c_printf("CONF: IRQ %d for irqpassing", i1);
+    if (bits & 0x10000)  c_printf(" uses SIGIO\n");
+    else c_printf("\n");
+  }
+  else yyerror("wrong IRQ for irqpassing command: %d", i1);
+}
+
+static void set_irq_range(int bits, int i1, int i2) {
+  int i;
+  if ( (i1<3) || (i1>15) || (i2<3) || (i2>15) || (i1 > i2 ) ) {
+    yyerror("wrong IRQ range for irqpassing command: %d .. %d", i1, i2);
+  }
+  else {
+    for (i=i1; i<=i2; i++) config.sillyint |= (bits << i);
+    c_printf("CONF: range of IRQs for irqpassing %d .. %d", i1, i2);
+    if (bits & 0x10000)  c_printf(" uses SIGIO\n");
+    else c_printf("\n");
+  }
+}
+
+
+	/* errors & warnings */
+
+void yywarn(char* string, ...)
+{
+  va_list vars;
+  va_start(vars, string);
+  fprintf(stderr, "Warning: ");
+  vfprintf(stderr, string, vars);
+  fprintf(stderr, "\n");
+  va_end(vars);
+  warnings++;
+}
+
+void yyerror(char* string, ...)
+{
+  va_list vars;
+  va_start(vars, string);
+  if (include_stack_ptr != 0 && !last_include) {
+	  int i;
+	  fprintf(stderr, "In file included from %s:%d\n",
+		  include_fnames[0], include_lines[0]);
+	  for(i = 1; i < include_stack_ptr; i++) {
+		  fprintf(stderr, "                 from %s:%d\n",
+			  include_fnames[i], include_lines[i]);
+	  }
+	  last_include = 1;
+  }
+  fprintf(stderr, "Error in %s: (line %.3d) ", 
+	  include_fnames[include_stack_ptr], line_count);
+  vfprintf(stderr, string, vars);
+  fprintf(stderr, "\n");
+  va_end(vars);
+  errors++;
+}
+
+
+/*
+ * open_file - opens the configuration-file named *filename and returns
+ *             a file-pointer. The error/warning-counters are reset to zero.
+ */
+
+static FILE *open_file(char *filename)
+{
+  errors   = 0;                  /* Reset error counter */
+  warnings = 0;                  /* Reset counter for warnings */
+
+  if (!filename) return 0;
+  return fopen(filename, "r"); /* Open config-file */
+}
+
+/*
+ * close_file - Close the configuration file and issue a message about
+ *              errors/warnings that occured. If there were errors, the
+ *              flag early-exit is that, so dosemu won't really.
+ */
+
+static void close_file(FILE * file)
+{
+  if (file) fclose(file);                  /* Close the config-file */
+
+  if(errors)
+    fprintf(stderr, "%d error(s) detected while parsing the configuration-file\n",
+	    errors);
+  if(warnings)
+    fprintf(stderr, "%d warning(s) detected while parsing the configuration-file\n",
+	    warnings);
+
+  if (errors != 0)               /* Exit dosemu on errors */
+    {
+      config.exitearly = TRUE;
+    }
+}
+
+/* write_to_syslog */
+static void write_to_syslog(char *message)
+{
+  openlog("dosemu", LOG_PID, LOG_USER | LOG_NOTICE);
+  syslog(LOG_PID | LOG_USER | LOG_NOTICE, message);
+  closelog();
+}
+
+static void move_dosemu_lib_dir(char *path)
+{
+  CONFIG_SCRIPT = assemble_path(path, CONFIG_SCRIPT_NAME, 0);
+  DOSEMU_LIB_DIR = strdup(path);
+  setenv("DOSEMU_LIB_DIR", DOSEMU_LIB_DIR, 1);
+  DEXE_LOAD_PATH = strdup(DOSEMU_LIB_DIR);
+  KEYMAP_LOAD_BASE_PATH = assemble_path(path, "", 0);
+}
+
+static FILE *open_dosemu_users(void)
+{
+  PRIV_SAVE_AREA
+  FILE *fp;
+  static char *tx = "Cannot open %s, Please check installation via System Admin.\n";
+  enter_priv_off();
+  fp = open_file(DOSEMU_USERS_FILE);
+  leave_priv_setting();
+  if (fp) return fp;
+  fprintf(stderr, tx, DOSEMU_USERS_FILE);
+  fprintf(stdout, tx, DOSEMU_USERS_FILE);
+  return 0;
+}
+
+/* Parse Users for DOSEMU, by Alan Hourihane, alanh@fairlite.demon.co.uk */
+/* Jan-17-1996: Erik Mouw (J.A.K.Mouw@et.tudelft.nl)
+ *  - added logging facilities
+ * In 1998:     Hans
+ *  - havy changes and re-arangments
+ */
+void
+parse_dosemu_users(void)
+{
+#define ALL_USERS "all"
+#define PBUFLEN 256
+
+  FILE *volatile fp;
+  struct passwd *pwd;
+  char buf[PBUFLEN];
+  int userok = 0;
+  char *ustr;
+  int log_syslog=0;
+  int uid;
+  int have_vars=0;
+
+  /* We come here _very_ early (at top of main()) to avoid security conflicts.
+   * priv_init() has already been called, but nothing more.
+   *
+   * We will exit, if /etc/dosemu.users says that the user has no right
+   * to run a suid root dosemu (and we are on), but will continue, if the user
+   * is running a non-suid copy _and_ is mentioned in dosemu users.
+   * The dosemu.users entry for such a user is:
+   *
+   *      joeodd  ... nosuidroot
+   *
+   * The functions we call rely on the following setting:
+   */
+  after_secure_check = 0;
+  priv_lvl = 0;
+
+  /* We first have to find out where the dosemu.users file is placed
+   * by the system administrator.
+   * We first look for /etc/dosemu.users, then for /etc/dosemu/dosemu.users
+   * Once we know that, most other pathes are runtime configurable:
+   *
+   *  - dosemu.users tells were to find the dosemu-lib-dir
+   *    (/var/lib/dosemu per default) which _must_ hold global.conf.
+   *  - global.conf includes $DOSEMU_CONF_DIR/dosemu.conf
+   *    (which could be changed by the owner of global.conf).
+   */
+  if (!exists_file(DOSEMU_USERS_FILE)) {
+    DOSEMU_USERS_FILE = ALTERNATE_ETC "/" DOSEMU_USERS;
+    if (!exists_file(DOSEMU_USERS_FILE)) {
+      static char *tx = "neither /etc nor " ALTERNATE_ETC " do contain " DOSEMU_USERS "\n";
+      fprintf(stderr, tx);
+      fprintf(stdout, tx);
+      exit(1);
+    }
+    DOSEMU_LOGLEVEL_FILE = ALTERNATE_ETC "/" DOSEMU_LOGLEVEL;
+    setenv("DOSEMU_CONF_DIR", ALTERNATE_ETC, 1);
+  }
+  else setenv("DOSEMU_CONF_DIR", "/etc", 1);
+
+  /* we check for some vital global settings
+   * which we need before proceeding
+   */
+  setenv("DOSEMU_LIB_DIR", DOSEMULIB_DEFAULT, 1);
+  fp = open_dosemu_users();
+  if (!fp) exit(1);
+  while (fgets(buf, PBUFLEN, fp) != NULL) {
+    int l = strlen(buf);
+    if (l && (buf[l-1] == '\n')) buf[l-1] = 0;
+    ustr = strtok(buf, " \t\n=,;:");
+    if (ustr && (ustr[0] != '#')) {
+      if (!strcmp(ustr, "default_lib_dir")) {
+        ustr=strtok(0, " \t\n=,;:");
+        if (ustr) {
+          if (!exists_dir(ustr)) {
+            static char *tx = "default_lib_dir %s not existing\n";
+            fprintf(stderr, tx, ustr);
+            fprintf(stdout, tx, ustr);
+            exit(1);
+          }
+          move_dosemu_lib_dir(ustr);
+        }
+      }
+      else if (!strcmp(ustr, "log_level")) {
+        int ll = 0;
+        ustr=strtok(0, " \t\n=,;:");
+        if (ustr) {
+          ll = atoi(ustr);
+          if (ll < 0) ll = 0;
+          if (ll > 2) ll = 2;
+        }
+        log_syslog = ll;
+      }
+    }
+  }
+  fclose(fp);
+
+
+  /* get our own hostname and define it as 'h_hostname'
+   * and in $DOSEMU_HOST
+   */
+  {
+    char buf [128];
+    int l;
+    /* preset DOSEMU_HOST env, such that the user may not fake an other */
+    setenv("DOSEMU_HOST", "unknown", 1);
+    if (!gethostname(buf+2, sizeof(buf)-1-2)) {
+      buf[0]='h';
+      buf[1]='_';
+      l=strlen(buf+2);
+      if (!getdomainname(buf+2+1+l, sizeof(buf)-1-2-l)) {
+        if (buf[2+1+l] && strncmp(buf+2+1+l, "(none)", 6)) buf[2+l]='.';
+        define_config_variable(buf);
+        setenv("DOSEMU_HOST", buf+2, 1);
+      }
+    }
+  }
+
+  /* We want to test if the _user_ is allowed to run Dosemu,             */
+  /* so check if the username connected to the get_orig_uid() is in the  */
+  /* DOSEMU_USERS_FILE file (usually /etc/dosemu.users).                  */
+   
+  uid = get_orig_uid();
+
+  pwd = getpwuid(uid);
+
+  /* Sanity Check, Shouldn't be anyone logged in without a userid */
+  if (pwd  == (struct passwd *)0) 
+     {
+       fprintf(stderr, "Illegal User!!!\n");
+       sprintf(buf, "Illegal DOSEMU user: uid=%i", uid);
+       write_to_syslog(buf);
+       exit(1);
+     }
+
+  /* preset DOSEMU_*USER env, such that a user can't fake it */
+  setenv("DOSEMU_USER", "unknown", 1);
+  setenv("DOSEMU_REAL_USER", pwd->pw_name, 1);
+
+  {
+       int can_have_privsetup = 0;
+       fp = open_dosemu_users();
+       if (fp) {
+	   for(userok=0; fgets(buf, PBUFLEN, fp) != NULL && !userok; ) {
+	     int l = strlen(buf);
+	     if (l && (buf[l-1] == '\n')) buf[l-1] = 0;
+	     ustr = strtok(buf, " \t\n,;:");
+	     if (ustr && (ustr[0] != '#')) {
+	       if (strcmp(ustr, pwd->pw_name)== 0) 
+		 userok = 1;
+	       else if (strcmp(ustr, ALL_USERS)== 0)
+		 userok = 1;
+	       if (userok) {
+		 setenv("DOSEMU_USER", ustr, 1);
+		 while ((ustr=strtok(0, " \t,;:")) !=0) {
+		   if (ustr[0] == '#') break;
+		   define_config_variable(ustr);
+		   have_vars = 1;
+                   if (!under_root_login && can_do_root_stuff && !strcmp(ustr,"nosuidroot")) {
+                     fprintf(stderr,
+                       "\nSorry, you are not allowed to run this suid root binary\n"
+                       "but you may run a non-suid root copy of it\n\n");
+                     exit(1);
+                   }
+                   if (!strcmp(ustr,"private_setup")) {
+                     can_have_privsetup = 1;
+                   }
+		 }
+		 if (!have_vars) {
+		   if (uid) define_config_variable("c_normal");
+		   else define_config_variable("c_all");
+		   have_vars = 1;
+		 }
+	       }
+	     }
+	   }
+           fclose(fp);
+       }
+
+       if (can_have_privsetup
+              && (   get_config_variable("unrestricted")
+                  || under_root_login || !can_do_root_stuff)) {
+         /* this user is allowed to have a privat ~/.dosemu/lib
+          * (which replaces DOSEMULIB_DEFAULT if existing).
+          * Hence this user can have its own global.conf e.t.c.
+          * However, this is only possible with non-suid-root
+          * binary or when running under root loggin or when 'unrestricted'
+          * also is set.       -- Hans
+          */
+         char *lpath = get_path_in_HOME(LOCALDIR_BASE_NAME "/lib");
+         if (exists_dir(lpath)) move_dosemu_lib_dir(lpath);
+         free(lpath);
+       }
+  }
+
+  if (uid == 0) {
+     if (!have_vars) define_config_variable("c_all");
+     userok=1;  /* This must be root, so always allow DOSEMU start */
+  }
+
+  if(userok==0) {
+       fprintf(stderr,
+	       "Sorry %s. You are not allowed to use DOSEMU. Contact System Admin.\n",
+	       pwd->pw_name);
+       if(log_syslog>=1) {
+	   fprintf(stderr, "This event will be logged!\n");
+           sprintf(buf, "Illegal DOSEMU start attempt by %s (uid=%i)", 
+           pwd->pw_name, uid);
+	   write_to_syslog(buf);
+       }
+       exit(1);
+  }
+  else {
+    if(log_syslog>=2) {
+       sprintf(buf, "DOSEMU started%s by %s (uid/euid=%i/%i)",
+            (can_do_root_stuff && !under_root_login)? " suid root" : "",
+            pwd->pw_name, uid, get_orig_euid());
+       write_to_syslog(buf);
+    }
+  }
+
+  /* now we setup up our local DOSEMU home directory, where we
+   * have (among other things) all temporary stuff in
+   * (since 0.97.10.2)
+   */
+  LOCALDIR = get_dosemu_local_home();
+  TMPDIR = mkdir_under(LOCALDIR, "tmp", 0);
+  TMPDIR_PROCESS = mkdir_under(TMPDIR, "temp.", 1);
+  RUNDIR = mkdir_under(LOCALDIR, "run", 0);
+  TMPFILE = assemble_path(RUNDIR, "dosemu.", 0);
+  DOSEMU_MIDI_PATH = assemble_path(RUNDIR, DOSEMU_MIDI, 0);
+
+  after_secure_check = 1;
+}
+
+
+char *commandline_statements=0;
+
+static int has_dexe_magic(char *name)
+{
+  PRIV_SAVE_AREA
+  int fd, magic, ret;
+  enter_priv_off();
+  fd = open(name, O_RDONLY);
+  leave_priv_setting();
+  if (fd <0) return 0;
+  ret = (read(fd, &magic, 4) == 4) && (magic == DEXE_MAGIC);
+  close(fd);
+  return ret;
+}
+
+static int stat_dexe(char *name)
+{
+  struct stat s;
+  extern int is_in_groups(gid_t);
+  if (stat(name, &s)) return 0;
+  if ( ! S_ISREG(s.st_mode)) return 0;
+  if ((s.st_mode & S_IXUSR) && (s.st_uid == get_orig_uid()))
+    return has_dexe_magic(name);
+  if ((s.st_mode & S_IXGRP) && (is_in_groups(s.st_gid)))
+    return  has_dexe_magic(name); 
+  if (s.st_mode & S_IXOTH) return has_dexe_magic(name);
+  return 0;
+}
+
+static char *resolve_exec_path(char *dexename, char *ext)
+{
+  enum { maxn=0x255 };
+  static char n[maxn+1];
+  static char name[maxn+1];
+  char *p, *path=getenv("PATH");
+
+  strncpy(name,dexename,maxn);
+  name[maxn] = 0;
+  n[maxn] = 0;
+  p = rindex(name, '.');
+  if ( ext && ((p && strcmp(p, ext)) || !p) )
+    strncat(name,ext,maxn);
+
+
+  /* first try the pure file name */
+  if (!path || (name[0] == '/') || (!strncmp(name, "./", 2))) {
+    if (stat_dexe(name)) return name;
+    return 0;
+  }
+
+  /* next try the standard path for DEXE files */
+  snprintf(n, maxn, "%s/%s", DEXE_LOAD_PATH, name);
+  if (stat_dexe(n)) return n;
+
+  /* now search in the users normal PATH */
+  path = strdup(path);
+  p= strtok(path,":");
+  while (p) {
+    snprintf(n, maxn, "%s/%s", p, name);
+    if (stat_dexe(n)) {
+      free(path);
+      return n;
+    }
+    p=strtok(0,":");
+  }
+  free(path);
+  return 0;
+}
+
+void prepare_dexe_load(char *name)
+{
+  PRIV_SAVE_AREA
+  char *n, *cbuf;
+  int fd, csize;
+  struct image_header ihdr;
+
+  enter_priv_on(); /* we need search rights for 'stat' */
+  n = resolve_exec_path(name, ".dexe");
+  if (!n) {
+    n = resolve_exec_path(name, 0);
+    if (!n) {
+      leave_priv_setting();
+      error("DEXE file not found or not executable\n");
+      exit(1);
+    }
+  }
+  leave_priv_setting();
+
+  /* now we extract the configuration file and the access flags */
+  fd = open(n, O_RDONLY);
+  if (read(fd, &ihdr, sizeof(struct image_header)) != sizeof(struct image_header)) {
+    error("broken DEXE format, can't read image header\n");
+    close(fd);
+    exit(1);
+  }
+
+  lseek(fd, HEADER_SIZE + 0x200, SEEK_SET); /* just behind the MBR */
+  if ((read(fd, &csize, 4) != 4) || (csize > 0x2000)) {
+    error("broken DEXE format, configuration not found\n");
+    close(fd);
+    exit(1);
+  }
+  
+  /* we use the -I option to feed in the configuration,
+   * and we put ours in front of eventually existing options
+   */
+  if (commandline_statements) {
+    cbuf = malloc(csize+1+strlen(commandline_statements)+1);
+    read(fd, cbuf, csize);
+    cbuf[csize] = '\n';
+    strcpy(cbuf+csize+1, commandline_statements);
+  }
+  else {
+    cbuf = malloc(csize+1);
+    read(fd, cbuf, csize);
+    cbuf[csize] = 0;
+  }
+  commandline_statements = cbuf;
+  close(fd);
+
+  start_disk();
+  dptr->type = IMAGE;
+  dptr->header = HEADER_SIZE;
+  dptr->dev_name = n;
+  dptr->dexeflags = ihdr.dexeflags | DISK_IS_DEXE;
+  stop_disk(DISK);
+  dexe_running = 1;
+}
+
+
+static void do_parse(FILE* fp, char *confname, char *errtx)
+{
+        yyin = fp;
+        line_count = 1;
+	include_stack_ptr = 0;
+        c_printf("CONF: Parsing %s file.\n", confname);
+	file_being_parsed = strdup(confname);
+	include_fnames[include_stack_ptr] = file_being_parsed;
+	yyrestart(fp);
+        if (yyparse()) yyerror(errtx, confname);
+        close_file(fp);
+	include_stack_ptr = 0;
+	include_fnames[include_stack_ptr] = 0;
+	free(file_being_parsed);
+}
+
+int parse_config(char *confname, char *dosrcname)
+{
+  FILE *fd;
+  int is_user_config;
+#if YYDEBUG != 0
+  extern int yydebug;
+
+  yydebug  = 1;
+#endif
+
+  define_config_variable(PARSER_VERSION_STRING);
+
+#if 0 /* no longer needed, config.c only allows -F for root or non-suid-root */
+  if (get_config_variable("c_strict") && strcmp(confname, CONFIG_SCRIPT)) {
+     c_printf("CONF: use of option -F %s forbidden by /etc/dosemu.users\n",confname);
+     c_printf("CONF: using %s instead\n", CONFIG_SCRIPT);
+     confname = CONFIG_SCRIPT;
+  }
+#endif
+
+  /* Let's try confname if not null, and fail if not found */
+  /* Else try the user's own .dosrc (old) or .dosemurc (new) */
+  /* If that doesn't exist we will default to CONFIG_FILE */
+
+  { 
+    PRIV_SAVE_AREA
+    uid_t uid = get_orig_uid();
+
+    char *name;
+    int skip_dosrc = 0;
+
+    if (!dosrcname) {
+      name = get_path_in_HOME(DOSEMU_RC);
+      setenv("DOSEMU_RC", name, 1);
+      free(name);
+      name = get_path_in_HOME(OLD_DOS_RC);
+    }
+    else {
+      name = strdup(dosrcname);
+      setenv("DOSEMU_RC",name,1);
+      skip_dosrc = 1;
+    }
+
+    /* privileged options allowed? */
+    is_user_config = strcmp(confname, CONFIG_SCRIPT);
+    priv_lvl = uid != 0 && is_user_config;
+
+    /* DEXE together with option F ? */
+    if (priv_lvl && dexe_running) {
+      /* for security reasons we cannot allow this */
+      fprintf(stderr, "user cannot load DEXE file together with option -F\n");
+      exit(1);
+    }
+
+    if (is_user_config) define_config_variable("c_user");
+    else define_config_variable("c_system");
+    if (dexe_running) define_config_variable("c_dexerun");
+
+    if (strcmp(confname, "none")) {
+      enter_priv_on();
+      fd = open_file(confname);
+      leave_priv_setting();
+      if (!fd) {
+        if (!dexe_running) {
+          fprintf(stderr, "Cannot open base config file %s, Aborting DOSEMU.\n",confname);
+          exit(1);
+        }
+      }
+      else {
+	do_parse(fd, confname, "error in configuration file %s");
+      }
+    }
+    if (priv_lvl) undefine_config_variable("c_user");
+    else undefine_config_variable("c_system");
+
+    if (!get_config_variable(CONFNAME_V3USED)) {
+	/* we obviously have an old configuration file
+         * ( or a too simple one )
+	 * giving up
+	 */
+	yyerror("\nYour %s script or %s configuration file is obviously\n"
+		"an old style or a too simple one\n"
+		"Please read README.txt on how to upgrade\n", confname, CONFIG_FILE);
+	exit(1);
+    }
+
+    /* privileged options allowed for user's config? */
+    priv_lvl = uid != 0;
+    if (priv_lvl) define_config_variable("c_user");
+
+#if 0 /* we abandon the old .dosrc completely, -- Hans 981010 */
+    define_config_variable("c_dosrc");
+    if (!skip_dosrc && !get_config_variable("skip_dosrc")
+                    && ((fd = open_file(name)) != 0)) {
+      do_parse(fd, name, "error in user's configuration file %s");
+    }
+    undefine_config_variable("c_dosrc");
+#endif
+
+    /* Now we parse any commandline statements from option '-I'
+     * We do this under priv_lvl set above, so we have the same secure level
+     * as with .dosrc
+     */
+
+    if (commandline_statements) {
+      #define XX_NAME "commandline"
+      extern char *yy_vbuffer;
+
+      open_file(0);
+      define_config_variable("c_comline");
+      c_printf("Parsing " XX_NAME  " statements.\n");
+      yyin=0;				 /* say: we have no input file */
+      yy_vbuffer=commandline_statements; /* this is the input to scan */
+      do_parse(0, XX_NAME, "error in user's %s statement");
+      undefine_config_variable("c_comline");
+    }
+  }
+
+  /* check for global settings, that should know the whole settings
+   * This we only can do, after having parsed all statements
+   */
+
+  if (dexe_running) {
+    if (dexe_secure && get_orig_uid())
+      config.secure = 1;
+    /* force a BootC,
+     * regardless what ever was set in the config files
+     */
+    config.hdiskboot = 1;
+  }
+  else {
+    if (get_config_variable("c_dexeonly")) {
+       c_printf("CONF: only execution of DEXE files allowed\n");
+       fprintf(stderr, "only execution of DEXE files allowed\n");
+       leavedos(99);
+    }
+  }
+
+
+#ifdef TESTING
+  error("TESTING: parser is terminating program\n");
+  leavedos(0);
+#endif
+
+  return 1;
+}
+
+#define MAX_CONFIGVARIABLES 128
+char *config_variables[MAX_CONFIGVARIABLES+1] = {0};
+static int config_variables_count = 0;
+static int config_variables_last = 0;
+static int allowed_classes = -1;
+static int saved_allowed_classes = -1;
+
+
+
+static int is_in_allowed_classes(int mask)
+{
+  if (!(allowed_classes & mask)) {
+    yyerror("insufficient class privilege to use this configuration option\n");
+    leavedos(99);
+  }
+  return 1;
+}
+
+struct config_classes {
+	char *class;
+	int mask;
+} config_classes[] = {
+	{"c_all", CL_ALL},
+	{"c_normal", CL_ALL & (~(CL_SHELL | CL_VAR | CL_BOOT | CL_VPORT | CL_SECURE | CL_IRQ | CL_HARDRAM))},
+	{"c_fileext", CL_FILEEXT},
+	{"c_var", CL_VAR},
+	{"c_system", CL_ALL},
+	{"c_nice", CL_NICE},
+	{"c_floppy", CL_FLOPPY},
+	{"c_boot", CL_BOOT},
+	{"c_secure", CL_SECURE},
+	{"c_vport", CL_VPORT},
+	{"c_dpmi", CL_DPMI},
+	{"c_video", CL_VIDEO},
+	{"c_port", CL_PORT},
+	{"c_disk", CL_DISK},
+	{"c_x", CL_X},
+	{"c_sound", CL_SOUND},
+	{"c_irq", CL_IRQ},
+	{"c_dexe", CL_DEXE},
+	{"c_printer", CL_PRINTER},
+	{"c_hardram", CL_HARDRAM},
+	{"c_shell", CL_SHELL},
+	{0,0}
+};
+
+static int get_class_mask(char *name)
+{
+  struct config_classes *p = &config_classes[0];
+  while (p->class) {
+    if (!strcmp(p->class,name)) return p->mask;
+    p++;
+  }
+  return 0;
+}
+
+static void update_class_mask(void)
+{
+  int i, m;
+  allowed_classes = 0;
+  for (i=0; i< config_variables_count; i++) {
+    if ((m=get_class_mask(config_variables[i])) != 0) {
+      allowed_classes |= m;
+    }
+  }
+}
+
+static void enter_user_scope(int incstackptr)
+{
+  if (user_scope_level) return;
+  saved_priv_lvl = priv_lvl;
+  priv_lvl = 1;
+  saved_allowed_classes = allowed_classes;
+  allowed_classes = 0;
+  user_scope_level = incstackptr;
+  c_printf("CONF: entered user scope, includelevel %d\n", incstackptr-1);
+}
+
+static void leave_user_scope(int incstackptr)
+{
+  if (user_scope_level != incstackptr) return;
+  priv_lvl = saved_priv_lvl;
+  allowed_classes = saved_allowed_classes;
+  user_scope_level = 0;
+  c_printf("CONF: left user scope, includelevel %d\n", incstackptr-1);
+}
+
+char *get_config_variable(char *name)
+{
+  int i;
+  for (i=0; i< config_variables_count; i++) {
+    if (!strcmp(name, config_variables[i])) {
+      config_variables_last = i;
+      return config_variables[i];
+    }
+  }
+  return 0;
+}
+
+int define_config_variable(char *name)
+{
+  if (priv_lvl) {
+    if (strcmp(name, CONFNAME_V3USED) && strncmp(name, "u_", 2)) {
+      c_printf("CONF: not enough privilege to define config variable %s\n", name);
+      return 0;
+    }
+  }
+  if (!get_config_variable(name)) {
+    if (config_variables_count < MAX_CONFIGVARIABLES) {
+      config_variables[config_variables_count++] = strdup(name);
+      if (!priv_lvl) update_class_mask();
+    }
+    else {
+      if (after_secure_check)
+        c_printf("CONF: overflow on config variable list\n");
+      return 0;
+    }
+  }
+  if (after_secure_check)
+    c_printf("CONF: config variable %s set\n", name);
+  return 1;
+}
+
+static int undefine_config_variable(char *name)
+{
+  if (priv_lvl) {
+    if (strncmp(name, "u_", 2)) {
+      c_printf("CONF: not enough privilege to undefine config variable %s\n", name);
+      return 0;
+    }
+  }
+  if (get_config_variable(name)) {
+    int i;
+    if (!strcmp(name, CONFNAME_V3USED)) parser_version_3_style_used = 0;
+    free(config_variables[config_variables_last]);
+    for (i=config_variables_last; i<(config_variables_count-1); i++) {
+      config_variables[i] = config_variables[i+1];
+    }
+    config_variables_count--;
+    if (!priv_lvl) update_class_mask();
+    c_printf("CONF: config variable %s unset\n", name);
+    return 1;
+  }
+  return 0;
+}
+
+char *checked_getenv(const char *name)
+{
+  if (user_scope_level) {
+     char *s, *name_ = malloc(strlen(name)+sizeof(USERVAR_PREF));
+     strcpy(name_, USERVAR_PREF);
+     strcat(name_, name);
+     s = getenv(name_);
+     free(name_);
+     if (s) return s;
+  }
+  return getenv(name);
+}
+
+static void check_user_var(char *name)
+{
+	char *name_;
+	char *s;
+
+	if (user_scope_level) return;
+	name_ = malloc(strlen(name)+sizeof(USERVAR_PREF));
+	strcpy(name_, USERVAR_PREF);
+	strcat(name_, name);
+	s = getenv(name_);
+	if (s) {
+		if (getenv(name))
+			c_printf("CONF: variable %s replaced by user\n", name);
+		setenv(name, s, 1);
+		unsetenv(name_);
+	}
+	free(name_);
+}
+
+
+static char *run_shell(char *command)
+{
+	int pipefds[2];
+	pid_t pid;
+	char excode[16] = "1";
+
+	setenv("DOSEMU_SHELL_RETURN", excode, 1);
+	if (pipe(pipefds)) return strdup("");
+	pid = fork();
+	if (pid == -1) return strdup("");
+	if (!pid) {
+		/* child */
+		int ret;
+		close(pipefds[0]);	/* we won't read from the pipe */
+		dup2(pipefds[1], 1);	/* make the pipe child's stdout */
+		priv_drop();	/* drop any priviledges */
+		ret = system(command);
+			/* tell the parent: "we have finished",
+			 * this way we need not to play games with select()
+			 */
+		if (ret == -1) ret = errno;
+		else ret >>=8;
+		write(pipefds[1],"\0\0\0",4);
+		close(pipefds[1]);
+		_exit(ret);
+	}
+	else {
+		/* parent */
+		char *buf = 0;
+		int recsize = 128;
+		int bufsize = 0;
+		int ptr =0;
+		int ret;
+		int status;
+
+		close(pipefds[1]);	/* we won't write to the pipe */
+		do {
+			bufsize = ptr + recsize;
+			if (!buf) buf = malloc(bufsize);
+			else buf = realloc(buf, bufsize);
+			ret = read(pipefds[0], buf+ptr, recsize -1);
+			if (ret > 0) {
+				ptr += ret;
+			}
+		} while (ret >0 && *((int *)(buf+ptr-4)) );
+		close(pipefds[0]);
+		waitpid(pid, &status, 0);
+		buf[ptr] = 0;
+		if (!buf[0]) {
+			free(buf);
+			buf = strdup("");
+		}
+		sprintf(excode, "%d", WEXITSTATUS(status));
+		setenv("DOSEMU_SHELL_RETURN", excode, 1);
+		return buf;
+	}
+}
+
+
+struct for_each_entry {
+	char *list;
+	char *ptr;
+	int skip_restart;
+};
+
+#define FOR_EACH_DEPTH	16
+static struct for_each_entry *for_each_list = 0;
+
+static int for_each_handling(int loopid, char *varname, char *delim, char *list)
+{
+	struct for_each_entry *fe;
+	char * new;
+	char saved;
+	if (!for_each_list) {
+		int size = FOR_EACH_DEPTH * sizeof(struct for_each_entry);
+		for_each_list = malloc(size);
+		memset(for_each_list, 0, size);
+	}
+	if (loopid > FOR_EACH_DEPTH) {
+		yyerror("too deeply nested foreach\n");
+		return 0;
+	}
+	fe = for_each_list + loopid;
+	if (!fe->list) {
+		/* starting the loop */
+		fe->ptr = fe->list = strdup(list);
+		fe->skip_restart = 0;
+		if (loopid) {
+			/* in inner loops we need to skip the restart */
+			fe->skip_restart = 1;
+		}
+	}
+	else {
+		if (fe->skip_restart) {
+			fe->skip_restart = 0;
+			return 1;
+		}
+	}
+	while (fe->ptr[0] && strchr(delim,fe->ptr[0])) fe->ptr++;
+	/* subsequent call */
+	if (!fe->ptr[0]) {
+		/* loop end */
+		free(fe->list);
+		fe->list = 0;
+		return (0);
+	}
+	new = strpbrk(fe->ptr, delim);
+	if (!new) new = strchr(fe->ptr,0);
+	saved = *new;
+	*new = 0;
+	setenv(varname,fe->ptr,1);
+	if (saved) new++;
+	fe->ptr = new;
+	return (1);
+}
+
+#ifdef TESTING_MAIN
+
+static void die(char *reason)
+{
+  error("par dead: %s\n", reason);
+  leavedos(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  if (argc != 2)
+    die("no filename!");
+
+  if (!parse_config(argv[1], argv[2] /* will be NULL if not given */))
+    die("parse failed!\n");
+}
+
+#endif
diff -Nur dosemu-1.0.1/src/base/serial/Makefile dosemu-1.0.1-mauspatch/src/base/serial/Makefile
--- dosemu-1.0.1/src/base/serial/Makefile	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/base/serial/Makefile	Thu Sep 14 22:19:58 2000
@@ -10,15 +10,15 @@
 SUBDIR=serial
 
 #The C files, include files and dependancies here.
-CFILES = ser_init.c ser_irq.c ser_ports.c int14.c fossil.c
-DEPENDS= ser_init.d ser_irq.d ser_ports.d int14.d fossil.d
+CFILES = ser_init.c ser_irq.c ser_ports.c int14.c fossil.c ext_fos.c
+DEPENDS= ser_init.d ser_irq.d ser_ports.d int14.d fossil.d ext_fos.d
 HFILES = ser_defs.h
 
 # Insert all source- and header-files here.
 ALL = $(CFILES) $(HFILES) README.serial
 
 # All object-files are included here.
-OBJS = ser_init.o ser_irq.o ser_ports.o int14.o fossil.o
+OBJS = ser_init.o ser_irq.o ser_ports.o int14.o fossil.o ext_fos.o
 
 all: lib
 
diff -Nur dosemu-1.0.1/src/base/serial/ext_fos.c dosemu-1.0.1-mauspatch/src/base/serial/ext_fos.c
--- dosemu-1.0.1/src/base/serial/ext_fos.c	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/src/base/serial/ext_fos.c	Thu Sep 14 22:19:58 2000
@@ -0,0 +1,131 @@
+/* DANG_BEGIN_MODULE
+ * 
+ * ext_fos.c: FOSSIL extended serial driver emulator for dosemu helper.
+ * 
+ * Copyright (C) 1998 by Christophe Saout.
+
+ * The code in this module is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
+ *
+ * DANG_END_MODULE
+*/
+
+#include <stdio.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "config.h" 
+#include "emu.h"
+#include "serial.h"
+#include "ser_defs.h"
+
+void ext_fos_func(int func,int port)
+{ int           n,flags;
+  unsigned char *p;
+  if (port < 0 || port >= config.num_ser)
+   return;
+  p = SEG_ADR((unsigned char *),es,di);
+  n = LWORD(ecx);
+  flags = LWORD(ebx);
+  switch(func)
+   { case 0: /* write data to device */
+             LWORD(eax) = RPT_SYSCALL(write(com[port].fd,p,n));
+             break;
+
+     case 1: /* read data from device */
+             LWORD(eax) = RPT_SYSCALL(read(com[port].fd,p,n));
+             break;
+
+     case 2: /* set speed and flags */
+             com[port].dlm = (n >> 8) & 0xff;
+             com[port].dll = n & 0xff;
+             com[port].LCR = flags & 0xff;
+             ser_termios(port);
+             break;
+
+     case 3: /* get timer ticks since last call */
+           { static struct timeval tp;
+             static struct timeval oldtp;
+             static long elapsed;
+
+             gettimeofday(&tp, NULL);
+
+             elapsed  = (tp.tv_sec - oldtp.tv_sec) * 115200;
+             elapsed += ((tp.tv_usec - oldtp.tv_usec) * 1152) / 10000;
+             if (elapsed < 0)
+              elapsed = 0;
+
+             oldtp = tp;
+             LWORD(eax) = (short)elapsed;
+             LWORD(edx) = (short)(elapsed >> 16);
+             break;
+           }
+     case 4: /* get dsr, cts, ri, dcd */
+           { int control;
+             int output = 0;
+             ioctl(com[port].fd,TIOCMGET,&control);
+             if (control & TIOCM_DSR) output |= 8;
+             if (control & TIOCM_CTS) output |= 4;
+             if (control & TIOCM_RNG) output |= 2;
+             if (control & TIOCM_CAR) output |= 1;
+             LWORD(eax) = output;
+             break;
+           }
+     case 5: /* set dtr */
+           { int control = TIOCM_DTR;
+             if (flags & 1)
+              ioctl(com[port].fd,TIOCMBIS,&control);
+             else
+              ioctl(com[port].fd,TIOCMBIC,&control);
+             break;
+           }
+     case 6: /* clear input */
+             tcflush(com[port].fd,TCIFLUSH);
+             break;
+
+     case 7: /* clear output */
+             tcflush(com[port].fd,TCOFLUSH);
+             break;
+
+     case 8: /* activate/deactive fossil on port */
+             if (flags)
+              { if (!com[port].fossil_active)
+                 { struct termios set;
+                   RPT_SYSCALL(tcgetattr(com[port].fd,&set));
+                   set.c_cflag |= CRTSCTS;
+                   RPT_SYSCALL(tcsetattr(com[port].fd,TCSANOW,&set));
+                 }
+                com[port].fossil_active = 2;
+              }
+             else
+              { if (com[port].fossil_active)
+                 { struct termios set;
+                   RPT_SYSCALL(tcgetattr(com[port].fd,&set));
+                   if (!com[port].system_rtscts) set.c_cflag &= ~CRTSCTS;
+                   tcsetattr(com[port].fd,TCSANOW,&set);
+                 }
+                com[port].fossil_active = 0;
+              }
+             break;
+   }
+}
+
+void ext_fos_timer(int port)
+{ /*struct termios set;
+  char str[16],*q;
+  unsigned short *p;
+  tcgetattr(com[port].fd,&set);
+  p = 0xB8000+(80-8)*2;
+  sprintf(str,"%08X",set.c_cflag);
+  for(q = str; *q; q++)
+   *p++ = 0x0700 | *q;
+  p = 0xB8000+(80+80-8)*2;
+  sprintf(str,"%08X",CRTSCTS);
+  for(q = str; *q; q++)
+   *p++ = 0x0700 | *q;*/
+}
diff -Nur dosemu-1.0.1/src/base/serial/fossil.c dosemu-1.0.1-mauspatch/src/base/serial/fossil.c
--- dosemu-1.0.1/src/base/serial/fossil.c	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/base/serial/fossil.c	Thu Sep 14 22:19:58 2000
@@ -72,7 +72,7 @@
  * is loaded. This module does nothing as long as this flag is false,
  * so other (DOS-based) FOSSIL drivers may be used. 
  */
-static boolean fossil_tsr_installed = FALSE;
+static boolean fossil_tsr_installed = 0;
 
 
 /**************************************************************************/
@@ -85,6 +85,8 @@
  */
 void fossil_int14(int num)
 {
+  if (fossil_tsr_installed == 2)
+   return;
   switch (HI(ax)) {
   /* Initialize serial port. */
   case 0x00:
@@ -162,7 +164,7 @@
     /* Do nothing if TSR isn't installed. */
     if (!fossil_tsr_installed)	     
       return;
-    com[num].fossil_active = TRUE;
+    com[num].fossil_active = 1;
     LWORD(eax) = FOSSIL_MAGIC;
     HI(bx) = FOSSIL_REVISION;
     LO(bx) = FOSSIL_MAX_FUNCTION;
@@ -350,17 +352,40 @@
   /* TSR installation check. */
   case 0:
     LWORD(eax) = fossil_tsr_installed;
+    if (LWORD(ebx) == 0x1234)
+     LWORD(ebx) = 0x4321;
     s_printf("SER: FOSSIL helper 0: TSR installation check, AX=%d\n", fossil_tsr_installed);
     break;
   
   /* TSR install. */
   case 1:
-    fossil_tsr_installed = TRUE;
+    fossil_tsr_installed = 1;
     fossil_id_segment = LWORD(es);
     fossil_id_offset = LWORD(edi);
     s_printf("SER: FOSSIL helper 1: TSR install, ES:DI=%04x:%04x\n", fossil_id_segment, fossil_id_offset);
     break;
   
+  case 2:
+    if (fossil_tsr_installed ^= 2) {
+      fossil_id_segment = LWORD(es);
+      fossil_id_offset = LWORD(edi);
+      LWORD(ebx) = config.num_ser;
+      s_printf("SER: Dosemu FOSSIL driver install, ES:DI=%04x:%04xßn",fossil_id_segment,fossil_id_offset);
+    }
+    else
+     { int i;
+       LWORD(es) = fossil_id_segment;
+       LWORD(edi) = fossil_id_offset;
+       for(i = 0; i < config.num_ser; i++)
+        com[i].fossil_active = 0;
+     }
+    LWORD(eax) = 0x1234;
+    break;
+
+  case 3:
+    if (fossil_tsr_installed == 2)
+     ext_fos_func(HI(dx),LO(dx));
+
   default:
     s_printf("SER: FOSSIL helper 0x%02x: Unknown function!\n", HI(ax));
   }
diff -Nur dosemu-1.0.1/src/base/serial/ser_defs.h dosemu-1.0.1-mauspatch/src/base/serial/ser_defs.h
--- dosemu-1.0.1/src/base/serial/ser_defs.h	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/base/serial/ser_defs.h	Thu Sep 14 22:19:58 2000
@@ -303,6 +303,8 @@
 void uart_clear_fifo(int, int);
 void pic_serial_run(void);
 void fossil_int14(int);
+void ext_fos_func(int,int);
+void ext_fos_timer(int);
 void ser_termios(int num);
 void modstat_engine(int num);
 inline int msr_compute_delta_bits(int oldmsr, int newmsr);
diff -Nur dosemu-1.0.1/src/base/serial/ser_irq.c dosemu-1.0.1-mauspatch/src/base/serial/ser_irq.c
--- dosemu-1.0.1/src/base/serial/ser_irq.c	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/base/serial/ser_irq.c	Thu Sep 14 22:19:58 2000
@@ -566,10 +566,13 @@
    * All the engines have built-in code to prevent loading the
    * system if they are called 100x's per second.
    */
-  for (i = 0; !into_irq && (i < config.num_ser); i++) {
-    receive_engine(i);		/* Receive operations */
-    transmit_engine(i);		/* Transmit operations */
-    modstat_engine(i);  	/* Modem Status operations */
-  }
+  for (i = 0; !into_irq && (i < config.num_ser); i++)
+   if (com[i].fossil_active == 2) {
+     ext_fos_timer(i);
+   } else {
+     receive_engine(i);                /* Receive operations */
+     transmit_engine(i);       /* Transmit operations */
+     modstat_engine(i);        /* Modem Status operations */
+   }
   return;
 }
diff -Nur dosemu-1.0.1/src/base/serial/ser_ports.c dosemu-1.0.1-mauspatch/src/base/serial/ser_ports.c
--- dosemu-1.0.1/src/base/serial/ser_ports.c	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/base/serial/ser_ports.c	Thu Sep 14 22:19:58 2000
@@ -397,8 +397,12 @@
   /* The following does the actual system calls to set the line parameters */
   cfsetispeed(&com[num].newset, baud);
   cfsetospeed(&com[num].newset, baud);
+  if (com[num].fossil_active == 2)
+   com[num].newset.c_cflag |= CRTSCTS;
   tcsetattr(com[num].fd, TCSANOW, &com[num].newset);
-
+  if (com[num].fossil_active == 2)
+   com[num].newset.c_cflag &= ~CRTSCTS;
+   
 #if 0
   /* Many mouse drivers require this, they detect for Framing Errors
    * coming from the mouse, during initialization, usually right after
@@ -934,6 +938,8 @@
 do_serial_in(int num, ioport_t address)
 {
   static int val;
+  if (com[num].fossil_active == 2)
+   return(0xff);
   switch (address - com[num].base_port) {
   case UART_RX:		/* Read from Received Byte Register */	
 /*case UART_DLL:*/      /* or Read from Baudrate Divisor Latch LSB */
@@ -1016,6 +1022,8 @@
 int
 do_serial_out(int num, ioport_t address, int val)
 {
+  if (com[num].fossil_active == 2)
+   return(0xff);
   switch (address - com[num].base_port) {
   case UART_TX:		/* Write to Transmit Holding Register */
 /*case UART_DLL:*/	/* or write to Baudrate Divisor Latch LSB */
diff -Nur dosemu-1.0.1/src/dosext/mfs/mfs.c dosemu-1.0.1-mauspatch/src/dosext/mfs/mfs.c
--- dosemu-1.0.1/src/dosext/mfs/mfs.c	Sun Mar  5 13:57:37 2000
+++ dosemu-1.0.1-mauspatch/src/dosext/mfs/mfs.c	Thu Sep 14 22:19:58 2000
@@ -1476,6 +1476,12 @@
 
   Debug0((dbg_fd, "emufs operation: 0x%08lx\n", state->ebx));
 
+  if (WORD(state->ebx) == 0x4dd4) {
+    static __inline__ void hlist_pop_psp(unsigned psp);
+    hlist_pop_psp((WORD(state->ecx) << 16) | WORD(state->edx));
+    return UNCHANGED;
+  }
+
   if (WORD(state->ebx) == 0x500) {
     init_all_drives();
     mach_fs_enabled = TRUE;
diff -Nur dosemu-1.0.1/src/include/emu.h dosemu-1.0.1-mauspatch/src/include/emu.h
--- dosemu-1.0.1/src/include/emu.h	Thu Sep 14 22:18:46 2000
+++ dosemu-1.0.1-mauspatch/src/include/emu.h	Thu Sep 14 22:19:58 2000
@@ -369,6 +369,7 @@
        char *sb_dsp;
        char *sb_mixer;
        __u16 mpu401_base;
+       int  int1a_allow_stime;
      }
 
 config_t;
diff -Nur dosemu-1.0.1/src/include/emu.h.orig dosemu-1.0.1-mauspatch/src/include/emu.h.orig
--- dosemu-1.0.1/src/include/emu.h.orig	Thu Jan  1 01:00:00 1970
+++ dosemu-1.0.1-mauspatch/src/include/emu.h.orig	Thu Sep 14 22:18:46 2000
@@ -0,0 +1,575 @@
+/* 
+ * (C) Copyright 1992, ..., 2000 the "DOSEMU-Development-Team".
+ *
+ * for details see file COPYING in the DOSEMU distribution
+ */
+
+/* dos emulator, Matthias Lautner 
+ * Extensions by Robert Sanders, 1992-93
+ *
+ */
+
+#ifndef EMU_H
+#define EMU_H
+
+#include <features.h>
+#include <sys/types.h>
+#include <setjmp.h>
+#if GLIBC_VERSION_CODE == 2000
+#include <sigcontext.h>
+#endif
+#include <signal.h> 
+#include "config.h"
+#include "types.h"
+#include "extern.h"
+#include "machcompat.h"
+#include "cpu.h"
+#include "vm86plus.h"
+#include "priv.h"
+
+#include "extern.h"
+
+#if 1 /* Set to 1 to use Silly Interrupt generator */
+#define SIG 1
+typedef struct { int fd; int irq; } SillyG_t;
+#endif
+
+#define inline __inline__
+
+#define BIT(x)  	(1<<x)
+
+#define us unsigned short
+
+/*
+ * DANG_BEGIN_REMARK
+   The `vm86_struct` is used to pass all the necessary status/registers to
+   DOSEMU when running in vm86 mode.
+ * DANG_END_REMARK
+*/ 
+
+EXTERN struct vm86plus_struct vm86s INIT ( {
+   {0},0,0,0,{{0}},{{0}}, {0}
+} );
+
+EXTERN volatile sig_atomic_t signal_pending INIT(0);
+EXTERN fd_set fds_sigio, fds_no_sigio;
+EXTERN unsigned int use_sigio INIT(0);
+EXTERN unsigned int not_use_sigio INIT(0);
+EXTERN int terminal_pipe;
+EXTERN int terminal_fd INIT(-1);
+EXTERN int running_kversion INIT(0);
+
+EXTERN char *cstack[16384];
+
+/* this is DEBUGGING code! */
+EXTERN int sizes INIT(0);
+
+EXTERN int screen, screen_mode;
+
+/* number of highest vid page - 1 */
+EXTERN int max_page INIT(7);
+
+#if 0
+/*
+ * 1) this stuff is unused
+ * 2) it should be FORBIDDEN to use global names less than 4 chars long!
+ */
+EXTERN char *cl,		/* clear screen */
+*le,				/* cursor left */
+*cm,				/* goto */
+*ce,				/* clear to end */
+*sr,				/* scroll reverse */
+*so,				/* stand out start */
+*se,				/* stand out end */
+*md,				/* hilighted */
+*mr,				/* reverse */
+*me,				/* normal */
+*ti,				/* terminal init */
+*te,				/* terminal exit */
+*ks,				/* init keys */
+*ke,				/* ens keys */
+*vi,				/* cursor invisible */
+*ve;				/* cursor normal */
+#endif
+
+/* the fd for the keyboard */ 
+EXTERN int console_fd INIT(-1);
+
+/* the file descriptor for /dev/mem mmap'ing */
+EXTERN int mem_fd INIT(-1);
+EXTERN int in_readkeyboard;
+
+/* X-pipes */
+EXTERN int keypipe;
+EXTERN int mousepipe;
+
+EXTERN int in_vm86 INIT(0);
+
+EXTERN int li, co;	/* lines, columns */
+EXTERN int scanseq;
+EXTERN int cursor_row;
+EXTERN int cursor_col;
+
+#if 0
+void dos_ctrl_alt_del(void);	/* disabled */
+#endif
+extern jmp_buf NotJEnv;
+
+EXTERN void run_vm86(void);
+EXTERN void loopstep_run_vm86(void);
+EXTERN void     vm86_GP_fault();
+
+EXTERN void do_call_back(Bit32u codefarptr);
+
+#define NOWAIT  0
+#define WAIT    1
+#define TEST    2
+#define POLL    3
+
+void getKeys(void);
+
+#include "dosemu_debug.h"
+
+     void char_out(u_char, int);
+
+     struct ioctlq {
+       int fd, req, param3;
+       int queued;
+     };
+
+     void do_queued_ioctl(void);
+     int queue_ioctl(int, int, int), do_ioctl(int, int, int);
+     void keybuf_clear(void);
+
+     int set_ioperm(int, int, int);
+
+EXTERN struct debug_flags d INIT({0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0});
+#ifdef DONT_DEBUG_BOOT
+EXTERN struct debug_flags d_save;
+#endif
+ 
+EXTERN u_char in_sighandler, in_ioctl;
+/* one-entry queue ;-( for ioctl's */
+EXTERN struct ioctlq iq INIT({0, 0, 0, 0}); 
+EXTERN u_char in_ioctl INIT(0);
+EXTERN struct ioctlq curi INIT({0, 0, 0, 0});
+
+
+/* this macro can be safely wrapped around a system call with no side
+ * effects; using a feature of GCC, it returns the same value as the
+ * function call argument inside.
+ *
+ * this is best used in places where the errors can't be sanely handled,
+ * or are not expected...
+ */
+#define DOS_SYSCALL(sc) ({ int s_tmp = (int)sc; \
+  if (s_tmp == -1) \
+    error("SYSCALL ERROR: %d, *%s* in file %s, line %d: expr=\n\t%s\n", \
+	  errno, strerror(errno), __FILE__, __LINE__, #sc); \
+  s_tmp; })
+
+#define SILENT_DOS_SYSCALL(sc) sc
+
+#if 0
+#define RPT_SYSCALL(sc) ({ int s_tmp, s_err; \
+   do { \
+	  s_tmp = sc; \
+	  s_err = errno; \
+	  if (errno == EINTR) {\
+	    g_printf("Recursive run_irqs() RPT_SYSCALL()\n"); \
+	    handle_signals(); \
+	/*    run_irqs(); */ \
+	  } \
+      } while ((s_tmp == -1) && (s_err == EINTR)); \
+  s_tmp; })
+#else
+#define RPT_SYSCALL(sc) (sc)
+#endif
+
+#define RPT_SYSCALL2(sc) ({ int s_tmp; \
+   do { \
+	  s_tmp = sc; \
+	  s_err = errno; \
+	  if (errno == EINTR) {\
+	    g_printf("Recursive run_irqs() RPT_SYSCALL2()\n"); \
+	    handle_signals(); \
+	/*    run_irqs(); */ \
+	  } \
+      } while ((s_tmp == -1) ); \
+  s_tmp; })
+
+#ifndef FALSE
+#define FALSE	0
+#endif
+#ifndef TRUE
+#define TRUE	1
+#endif
+
+#ifndef True
+#define True  TRUE
+#endif
+#ifndef False
+#define False FALSE
+#endif
+
+#ifndef DOSEMU_BOOL_IS_CHAR
+typedef unsigned char boolean;
+#define DOSEMU_BOOL_IS_CHAR
+#endif
+
+/* would like to have this in memory.h (but emu.h is included before memory.h !) */
+#define HARDWARE_RAM_START 0xc8000
+#define HARDWARE_RAM_STOP  0xf0000
+
+typedef struct vesamode_type_struct {
+  struct vesamode_type_struct *next;
+  unsigned width, height, color_bits;
+} vesamode_type;
+
+
+     typedef struct config_info {
+       int hdiskboot;
+
+       /* for video */
+       boolean console;
+       boolean console_video;
+       boolean graphics;
+       boolean vga;
+       boolean X;
+       u_short cardtype;
+       u_short chipset;
+       boolean pci;
+       boolean pci_video;
+       u_short gfxmemsize;		/* for SVGA card, in K */
+       /* u_short term_method; */	/* Terminal method: ANSI or NCURSES */
+       u_short term_color;		/* Terminal color support on or off */
+       /* u_short term_updatelines; */	/* Amount to update at a time */
+       u_short term_updatefreq;		/* Terminal update frequency */
+       u_short term_charset;		/* Terminal Character set */
+       u_short term_esc_char;	        /* ASCII value used to access slang help screen */
+       /* u_short term_corner; */       /* Update char at lower-right corner */
+       u_short X_updatelines;           /* Amount to update at a time */
+       u_short X_updatefreq;            /* X update frequency */
+       char    *X_display;              /* X server to use (":0") */
+       char    *X_title;                /* X window title */
+       char    *X_icon_name;
+       char    *X_font;
+       char    *X_mgrab_key;		/* KeySym name to activate mouse grab */
+					/* "" turns it of, NULL gives the default ("Home") */
+       int     X_blinkrate;
+       int     X_sharecmap;
+       int     X_mitshm;                /* use MIT SHM extension */
+       int     X_fixed_aspect;          /* keep initial aspect ratio while resizing windows */
+       int     X_aspect_43;             /* set aspect ratio to 4:3 */
+       int     X_lin_filt;              /* interpolate linear */
+       int     X_bilin_filt;            /* dto, bilinear */
+       int     X_winsize_x;             /* initial window width */
+       int     X_mode13fact;            /* initial size factor for mode 0x13 */
+       int     X_winsize_y;             /* initial window height */
+       unsigned X_gamma;		/* gamma correction value */
+       u_short vgaemu_memsize;		/* for VGA emulation */
+       vesamode_type *vesamode_list;	/* chained list of VESA modes */
+       int     X_lfb;			/* support VESA LFB modes */
+       int     X_pm_interface;		/* support protected mode interface */
+       boolean fullrestore;
+       boolean force_vt_switch;         /* in case of console_video force switch to emu VT at start */
+       int     dualmon;
+
+       u_short usesX;  /* !=0 if dosemu owns an X window */
+
+       boolean console_keyb;
+       boolean kbd_tty;
+       boolean X_keycode;	/* use keycode field of event structure */
+       boolean exitearly;
+       int     realcpu;
+       boolean mathco, smp;
+       boolean ipxsup;
+       boolean vnet;
+       boolean keybint;
+       boolean dosbanner;
+       boolean allowvideoportaccess;
+       boolean emuretrace;
+       boolean rdtsc;
+       boolean timers;
+       boolean mouse_flag;
+       boolean mapped_bios;	/* video BIOS */
+       char *vbios_file;	/* loaded VBIOS file */
+       boolean vbios_copy;
+       int vbios_seg;           /* VGA-BIOS-segment for mapping */
+       int vbios_size;          /* size of VGA-BIOS (64K for vbios_seg=0xe000
+       						     32K for vbios_seg=0xc000) */
+
+       boolean bootdisk;	/* Special bootdisk defined */
+       int  fastfloppy;
+       char *emusys;		/* map CONFIG.SYS to CONFIG.EMU */
+       char *emubat;		/* map AUTOEXEC.BAT to AUTOEXEC.EMU */
+       char *emuini;           /* map system.ini to  system.EMU */
+
+       u_short speaker;		/* 0 off, 1 native, 2 emulated */
+       u_short fdisks, hdisks;
+       u_short num_lpt;
+       u_short num_ser;
+       u_short num_mice;
+
+       int pktflags;		/* global flags for packet driver */
+
+       unsigned int update, freq;	/* temp timer magic */
+       unsigned int wantdelta, realdelta;
+       unsigned long cpu_spd;		/* (1/speed)<<32 */
+       unsigned long cpu_tick_spd;	/* (1.19318/speed)<<32 */
+
+       unsigned int hogthreshold;
+
+       int mem_size, xms_size, ems_size, dpmi, max_umb;
+       int secure;
+       unsigned int ems_frame;
+       char must_spare_hardware_ram;
+       char hardware_pages[ ((HARDWARE_RAM_STOP-HARDWARE_RAM_START) >> 12)+1 ];
+
+
+       int sillyint;            /* IRQ numbers for Silly Interrupt Generator 
+       				   (bitmask, bit3..15 ==> IRQ3 .. IRQ15) */
+
+       struct keytable_entry *keytable;
+
+       unsigned short detach;
+       unsigned char *debugout;
+       unsigned char *pre_stroke;  /* pointer to keyboard pre strokes */
+       unsigned char *pre_stroke_mem;
+
+       /* Lock File business */
+       char *tty_lockdir;	/* The Lock directory  */
+       char *tty_lockfile;	/* Lock file pretext ie LCK.. */
+       boolean tty_lockbinary;	/* Binary lock files ? */
+
+       /* type of mapping driver */
+       char *mappingdriver;
+
+       /* list of arbitrary features
+        * (at minimum 1, will be increased when needed)
+        * The purpose of these parameters is to switch between code
+        * or code pieces that in principal do the same, but for some
+        * unknown reasons behave different between machines.
+        * If a 'features' becomes obsolete (problem solved) it will
+        * remain dummy for a while before re-used.
+        *
+        * NOTE: 'features' are not subject to permanent documentation!
+        *       They should be considered 'temporary hacks'
+        *
+        * Currently assigned:
+        *
+        *   features[0]		use new(0) or old(1) Slangcode
+        */
+       int features[1];
+
+       /* Sound emulation */
+       __u16 sb_base;
+       __u8 sb_dma;
+       __u8 sb_irq;
+       char *sb_dsp;
+       char *sb_mixer;
+       __u16 mpu401_base;
+     }
+
+config_t;
+
+
+#define SPKR_OFF	0
+#define SPKR_NATIVE	1
+#define SPKR_EMULATED	2
+
+/*
+ * Right now, dosemu only supports two serial ports.
+ */
+#define SIG_SER		SIGTTIN
+
+#define SIG_TIME	SIGALRM
+#define TIMER_TIME	ITIMER_REAL
+
+#define IO_READ  1
+#define IO_WRITE 2
+#define IO_RDWR	 (IO_READ | IO_WRITE)
+
+#undef cli
+#undef sti
+EXTERN void cli(void);
+EXTERN void sti(void);
+EXTERN int port_readable(unsigned short);
+EXTERN int port_writeable(unsigned short);
+EXTERN unsigned char read_port(unsigned short);
+EXTERN int write_port(unsigned int, unsigned short);
+EXTERN __inline__ void parent_nextscan(void);
+EXTERN __inline__ void disk_close(void);
+EXTERN void cpu_setup(void);
+EXTERN void real_run_int(int);
+#ifdef USE_NEW_INT
+  #define run_int do_int
+#else
+  #define run_int real_run_int
+#endif
+EXTERN int mfs_redirector(void);
+EXTERN void int10(void);
+EXTERN void int13(u_char);
+EXTERN void int14(u_char);
+EXTERN void int17(u_char);
+EXTERN void io_select(fd_set);
+EXTERN int pd_receive_packet(void);
+EXTERN int printer_tick(u_long);
+EXTERN int printer_tick(u_long);
+EXTERN void floppy_tick(void);
+EXTERN void open_kmem(void);
+EXTERN void close_kmem(void);
+EXTERN void CloseNetworkLink(int);
+EXTERN int parse_config(char *, char *);
+EXTERN void disk_init(void);
+EXTERN void serial_init(void);
+EXTERN void close_all_printers(void);
+EXTERN void release_ports(void);
+EXTERN void serial_close(void);
+EXTERN void disk_close_all(void);
+EXTERN void init_all_printers(void);
+EXTERN int mfs_inte6(void);
+EXTERN void pkt_helper(void);
+EXTERN short pop_word(struct vm86_regs *);
+EXTERN void ems_init(void);
+EXTERN int GetDebugFlagsHelper(char *, int);
+EXTERN int SetDebugFlagsHelper(char *);
+EXTERN void leavedos(int) NORETURN;
+EXTERN void add_to_io_select(int, unsigned char);
+EXTERN void remove_from_io_select(int, unsigned char);
+EXTERN void sigquit(int);
+#ifdef __linux__
+EXTERN void sigalrm(int, struct sigcontext_struct);
+EXTERN void sigio(int, struct sigcontext_struct);
+EXTERN int dosemu_sigaction(int sig, struct sigaction *new, struct sigaction *old);
+#endif
+
+/* signals for Linux's process control of consoles */
+#define SIG_RELEASE     SIGWINCH
+#define SIG_ACQUIRE     SIGUSR2
+
+ /* DANG_BEGIN_REMARK
+  * We assume system call restarting... under linux 0.99pl8 and earlier,
+  * this was the default.  SA_RESTART was defined in 0.99pl8 to explicitly
+  * request restarting (and thus does nothing).  However, if this ever
+  * changes, I want to be safe
+  * DANG_END_REMARK
+  */
+#ifndef SA_RESTART
+#define SA_RESTART 0
+#error SA_RESTART Not defined
+#endif
+
+/* DANG_BEGIN_FUNCTION NEWSETQSIG
+ *
+ * arguments:
+ * sig - the signal to have a handler installed to.
+ * fun - the signal handler function to install
+ *
+ * description:
+ *  All signals that wish to be handled properly in context with the
+ * execution of vm86() mode, and signals that wish to use non-reentrant
+ * functions should add themselves to the ADDSET_SIGNALS_THAT_QUEUE define
+ * and use SETQSIG(). To that end they will also need to be set up in an
+ * order such as SIGIO.
+ *
+ * DANG_END_FUNCTION
+ *
+ */
+#define ADDSET_SIGNALS_THAT_QUEUE(x) \
+do { \
+       sigaddset(x, SIGIO); \
+       sigaddset(x, SIG_TIME); \
+       sigaddset(x, SIG_RELEASE); \
+       sigaddset(x, SIG_ACQUIRE); \
+} while(0)
+
+#ifdef __linux__
+#if GLIBC_VERSION_CODE
+#define SignalHandler __sighandler_t
+#endif
+#define NEWSETQSIG(sig, fun)	sa.sa_handler = (__sighandler_t)fun; \
+			/* Point to the top of the stack, minus 4 \
+			   just in case, and make it aligned  */ \
+			sa.sa_restorer = \
+			(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3); \
+					sa.sa_flags = SA_RESTART ; \
+					sigemptyset(&sa.sa_mask); \
+					ADDSET_SIGNALS_THAT_QUEUE(&sa.sa_mask); \
+					dosemu_sigaction(sig, &sa, NULL);
+
+#define SETSIG(sig, fun)	sa.sa_handler = (SignalHandler)fun; \
+					sa.sa_flags = SA_RESTART; \
+					sigemptyset(&sa.sa_mask); \
+					sigaddset(&sa.sa_mask, SIG_TIME); \
+					sigaction(sig, &sa, NULL);
+
+#define NEWSETSIG(sig, fun) \
+			sa.sa_handler = (__sighandler_t) fun; \
+			/* Point to the top of the stack, minus 4 \
+			   just in case, and make it aligned  */ \
+			sa.sa_restorer = \
+			(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3); \
+			sa.sa_flags = SA_RESTART; \
+			sigemptyset(&sa.sa_mask); \
+			sigaddset(&sa.sa_mask, SIG_TIME); \
+			dosemu_sigaction(sig, &sa, NULL);
+#endif
+
+EXTERN inline void SIGNAL_save( void (*signal_call)(void) );
+EXTERN inline void handle_signals(void);
+
+
+/* 
+ * DANG_BEGIN_REMARK
+ * DOSEMU keeps system wide configuration status in a structure
+ * called config.
+ * DANG_END_REMARK
+ */
+EXTERN struct config_info config;
+
+
+/*
+ * DANG_BEGIN_REMARK
+ * The var `fatalerr` can be given a true value at any time to have DOSEMU
+ * exit on the next return from vm86 mode.
+ * DANG_END_REMARK
+ */
+EXTERN int fatalerr INIT(0);
+
+/*
+ * DANG_BEGIN_REMARK
+ * The var 'running_DosC' is set by the DosC kernel and is used to handle
+ * some things differently, e.g. the redirector.
+ * It interfaces via INTe6,0xDC (DOS_HELPER_DOSC), but only if running_DosC
+ * is !=0. At the very startup DosC issues a INTe6,0xdcDC to set running_DosC
+ * with the contents of BX (which is the internal DosC version).
+ * DANG_END_REMARK
+ */
+EXTERN int running_DosC INIT(0);
+EXTERN int dosc_interface(void);
+
+EXTERN void signal_init(void);
+EXTERN void device_init(void);
+EXTERN void hardware_setup(void);
+EXTERN void memory_init(void);
+EXTERN void timer_interrupt_init(void);
+EXTERN void keyboard_flags_init(void);
+EXTERN void video_config_init(void);
+EXTERN void printer_init(void);
+EXTERN void video_close(void);
+EXTERN void hma_exit(void);
+EXTERN void ems_helper(void);
+EXTERN boolean_t ems_fn(struct vm86_regs *);
+EXTERN void serial_helper(void);
+EXTERN void mouse_helper(void);
+EXTERN void cdrom_helper(void);
+EXTERN void boot(void);
+EXTERN int pkt_int(void);
+EXTERN void read_next_scancode_from_queue (void);
+EXTERN unsigned short detach (void);
+EXTERN void HMA_init(void);
+
+extern char *Path_cdrom[];
+
+#endif /* EMU_H */
