[PENNMUSH-ANNOUNCE] 1.7.4-patch08

dunemush@pennmush.org dunemush at pennmush.org
Sat, 28 Jul 2001 09:05:30 -0500


This is patch08 to PennMUSH 1.7.4. After applying this patch, you will
have version 1.7.4p8

To apply this patch, save it to a file in your top-level MUSH directory,
and do the following:
	patch -p1 < 1.7.4-patch08
	make install

If you use GNU patch 2.2, you probably want the above to be 'patch -b -p1',
not just 'patch -p1'.

Unix (or cygwin) users need not worry about failed hunks in src/switchinc.c,
hdrs/switches.h, hdrs/cmds.h, or hdrs/funs.h. These files are automatically
rebuilt on compile.

Then @shutdown and restart your MUSH.
    - Alan/Javelin

In this patch:

Minor changes:
  * restart is a bit more precise in the "Mush already active" message.
    Suggested by Lucas Layman.
  * When a player's creation is refused because creation/registration
    is globally turned off, show them register.txt instead of down.txt.
    Patch by Bellemore.
  * The NOSPOOF flag is now visible only to the player themself. [SW]
  * regedit can now use backreferences in the replacer. [SW]
Fixes:
  * ident lookups were broken on win32. Reported by Bellemore. [SW] 
  * ident query timeouts could get doubled mistakenly. [SW]
  * Typo in mushcnf.dst fixed by Noltar@Korongil.
  * Fix to help puppets2 by TurtleKnee@M*U*S*H.
  * Help pcreate() added. Report by Eratl@M*U*S*H.
  * @pcreate messages capitalized by Oriens@Alexandria.
  * create() used 10 as the default cost, instead of the configured
    default. Report by 8bitMUSH.
  * Inactivity timeouts longer than 1 day didn't work. Fixed and
    efficiency of the check improved. Reported by Bellemore@M*U*S*H.
  * Null @aliases are no longer allowed. [SW]
  * Cleanup to ident for situations when the remote host isn't running
    an ident server. [SW]

Prereq: 1.7.4p7
*** 1_7_4.130/Patchlevel Mon, 02 Jul 2001 10:20:44 -0500 dunemush (pennmush/5_Patchlevel 1.25 600)
--- 1_7_4.137(w)/Patchlevel Sun, 22 Jul 2001 09:09:45 -0500 dunemush (pennmush/5_Patchlevel 1.25 600)
***************
*** 1,2 ****
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.4p7
--- 1,2 ----
  Do not edit this file. It is maintained by the official PennMUSH patches.
! This is PennMUSH 1.7.4p8
*** 1_7_4.130/CHANGES Tue, 10 Jul 2001 14:23:59 -0500 dunemush (pennmush/8_CHANGES 1.219.1.16 600)
--- 1_7_4.137(w)/CHANGES Wed, 25 Jul 2001 08:52:25 -0500 dunemush (pennmush/8_CHANGES 1.219.1.22 600)
***************
*** 17,22 ****
--- 17,47 ----
  
  ==========================================================================
  
+ Version 1.7.4 patchlevel 8		       July 22, 2001
+ 
+ Minor changes:
+   * restart is a bit more precise in the "Mush already active" message.
+     Suggested by Lucas Layman.
+   * When a player's creation is refused because creation/registration
+     is globally turned off, show them register.txt instead of down.txt.
+     Patch by Bellemore.
+   * The NOSPOOF flag is now visible only to the player themself. [SW]
+   * regedit can now use backreferences in the replacer. [SW]
+ Fixes:
+   * ident lookups were broken on win32. Reported by Bellemore. [SW] 
+   * ident query timeouts could get doubled mistakenly. [SW]
+   * Typo in mushcnf.dst fixed by Noltar@Korongil.
+   * Fix to help puppets2 by TurtleKnee@M*U*S*H.
+   * Help pcreate() added. Report by Eratl@M*U*S*H.
+   * @pcreate messages capitalized by Oriens@Alexandria.
+   * create() used 10 as the default cost, instead of the configured
+     default. Report by 8bitMUSH.
+   * Inactivity timeouts longer than 1 day didn't work. Fixed and
+     efficiency of the check improved. Reported by Bellemore@M*U*S*H.
+   * Null @aliases are no longer allowed. [SW]
+   * Cleanup to ident for situations when the remote host isn't running
+     an ident server. [SW]
+ 
  Version 1.7.4 patchlevel 7		       July 02, 2001
  
  Major changes:
*** 1_7_4.130/game/txt/hlp/pennvers.hlp Tue, 10 Jul 2001 14:23:59 -0500 dunemush (pennmush/12_pennvers.h 1.169.1.15 600)
--- 1_7_4.137(w)/game/txt/hlp/pennvers.hlp Wed, 25 Jul 2001 08:52:28 -0500 dunemush (pennmush/12_pennvers.h 1.169.1.19 600)
***************
*** 1,5 ****
  & changes
! & 1.7.4p7
  This is a list of changes in this patchlevel which are probably of
  interest to players. More information about new commands and functions
  can probably be gotten via 'help <name of whatever>'. 'help credits'
--- 1,5 ----
  & changes
! & 1.7.4p8
  This is a list of changes in this patchlevel which are probably of
  interest to players. More information about new commands and functions
  can probably be gotten via 'help <name of whatever>'. 'help credits'
***************
*** 11,16 ****
--- 11,42 ----
  A list of the patchlevels associated with each release can
  be read in 'help patchlevels'.
  
+ Version 1.7.4 patchlevel 8		       July 22, 2001
+ 
+ Minor changes:
+   * restart is a bit more precise in the "Mush already active" message.
+     Suggested by Lucas Layman.
+   * When a player's creation is refused because creation/registration
+     is globally turned off, show them register.txt instead of down.txt.
+     Patch by Bellemore.
+   * The NOSPOOF flag is now visible only to the player themself. [SW]
+   * regedit can now use backreferences in the replacer. [SW]
+ Fixes:
+   * ident lookups were broken on win32. Reported by Bellemore. [SW] 
+   * ident query timeouts could get doubled mistakenly. [SW]
+   * Typo in mushcnf.dst fixed by Noltar@Korongil.
+   * Fix to help puppets2 by TurtleKnee@M*U*S*H.
+   * Help pcreate() added. Report by Eratl@M*U*S*H.
+   * @pcreate messages capitalized by Oriens@Alexandria.
+   * create() used 10 as the default cost, instead of the configured
+     default. Report by 8bitMUSH.
+   * Inactivity timeouts longer than 1 day didn't work. Fixed and
+     efficiency of the check improved. Reported by Bellemore@M*U*S*H.
+   * Null @aliases are no longer allowed. [SW]
+   * Cleanup to ident for situations when the remote host isn't running
+     an ident server. [SW]
+ 
+ & 1.7.4p7
  Version 1.7.4 patchlevel 7		       July 02, 2001
  
  Major changes:
***************
*** 4771,4777 ****
  For information on a specific patchlevel of one of the versions listed,
  type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
  
! 1.7.4: 0, 1, 2, 3, 4, 5, 6, 7
  1.7.3: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  1.7.2: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
         19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
--- 4797,4803 ----
  For information on a specific patchlevel of one of the versions listed,
  type 'help <version>p<patchlevel>'. For example, 'help 1.7.2p3'
  
! 1.7.4: 0, 1, 2, 3, 4, 5, 6, 7, 8
  1.7.3: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
  1.7.2: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
         19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
*** 1_7_4.130/game/txt/hlp/penntop.hlp Fri, 08 Jun 2001 14:14:28 -0500 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.1 600)
--- 1_7_4.137(w)/game/txt/hlp/penntop.hlp Wed, 18 Jul 2001 12:07:35 -0500 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.2 600)
***************
*** 972,977 ****
--- 972,979 ----
  
    > @create Punch
    Created: Object #18.
+   > drop Punch
+   Dropped.
    > @set punch=puppet
    Punch is now listening.
    Flag set.
*** 1_7_4.130/game/txt/hlp/pennfunc.hlp Sat, 07 Jul 2001 21:06:09 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.3 600)
--- 1_7_4.137(w)/game/txt/hlp/pennfunc.hlp Thu, 19 Jul 2001 14:01:25 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.4 600)
***************
*** 204,214 ****
    create()      die()         dig()         emit()        functions()
    isdbref()     isint()       isnum()       isword()      lemit()
    localize()    link()        list()        lnum()        mudname()
!   null()        objeval()     oemit()       open()        pemit()
!   r-function    rand()        remit()       restarts()    s-function
!   set()         setq()        setr()        soundex()     soundslike()
!   tel()         valid()       version()     wipe()        zemit()
!   @@()
  
  & @@()
  & NULL()
--- 204,214 ----
    create()      die()         dig()         emit()        functions()
    isdbref()     isint()       isnum()       isword()      lemit()
    localize()    link()        list()        lnum()        mudname()
!   null()        objeval()     oemit()       open()        pcreate()
!   pemit()       r-function    rand()        remit()       restarts()    
!   s-function    set()         setq()        setr()        soundex()     
!   soundslike()  tel()         valid()       version()     wipe()        
!   zemit()       @@()
  
  & @@()
  & NULL()
***************
*** 575,580 ****
--- 575,586 ----
    cos(<number>)
   
    Returns the cosine of <number>, which should be expressed in radians.
+ & PCREATE()
+   pcreate(<name>,<password>)
+ 
+   Creates a player with a given name and password. Wizard-only.
+ 
+   See also: @pcreate
  & CREATE()
    create(<object>, <cost>)
   
***************
*** 2247,2263 ****
  
    These functions are a version of edit() that uses regular expressions.
    The part of <string> that matches the <regexp> is replaced by the
!   <replacement>, with $<number> in <replacement> expanded to the
    corresponding matching sub-expression of <regexp>, with $0 the entire
    matched section. regedit() only replaces the first match.
    regeditall() replaces all matches. The versions ending in i are
!   case insensitive.
  
    Example:
    > say regedit(this test is the best string, (.)est, $1rash)
    You say "this trash is the best string"
!   > say regeditall(this test is the best string, (.)est, $1rash)
!   You say "this trash is the brash string"
  
  See also: edit(), regmatch()
  & REGMATCH()
--- 2253,2271 ----
  
    These functions are a version of edit() that uses regular expressions.
    The part of <string> that matches the <regexp> is replaced by the
!   evaluated <replacement>, with $<number> in <replacement> expanded to the
    corresponding matching sub-expression of <regexp>, with $0 the entire
    matched section. regedit() only replaces the first match.
    regeditall() replaces all matches. The versions ending in i are
!   case insensitive. The <replacement> argument is evaluated once for
!   each match, allowing for more complex transformations than is
!   possible with straight replacement.
  
    Example:
    > say regedit(this test is the best string, (.)est, $1rash)
    You say "this trash is the best string"
!   > say regeditall(this test is the best string, (.)est, [capstr($1)]rash)
!   You say "this Trash is the Brash string"
  
  See also: edit(), regmatch()
  & REGMATCH()
*** 1_7_4.130/game/txt/hlp/pennchat.hlp Mon, 04 Dec 2000 10:36:58 -0600 dunemush (pennmush/19_pennchat.h 1.2.1.4 600)
--- 1_7_4.137(w)/game/txt/hlp/pennchat.hlp Wed, 25 Jul 2001 11:56:54 -0500 dunemush (pennmush/19_pennchat.h 1.2.1.4 600)
***************
*** 33,38 ****
--- 33,39 ----
    as normal, preventing user-defined commands like "+last" from
    being clobbered by the chat system.
  
+   See also: chat
  & @cemit
    @cemit[/noisy][/noeval] <channel>=<message>
  
***************
*** 42,47 ****
--- 43,49 ----
    is not evaluated. This command is intended for use in writing
    extended chat systems.
  
+   See also: chat
  & @channel
    @channel/list [<channel-prefix>]
    @channel/what [<channel-prefix>]
***************
*** 64,70 ****
    @channel/what will show you the channel's name, access information,
    and a description of the channel's purpose.
  
!   More details are provided in "help @channel2".
  & @channel2
    @channel/who <channel>
    @channel/hide <channel> = <yes|no>
--- 66,72 ----
    @channel/what will show you the channel's name, access information,
    and a description of the channel's purpose.
  
!   More details are provided in "help @channel2".  See also: chat
  & @channel2
    @channel/who <channel>
    @channel/hide <channel> = <yes|no>
*** 1_7_4.130/game/txt/register.txt Sat, 07 Apr 2001 09:19:53 -0500 dunemush (pennmush/24_register.t 1.1.2.1 600)
--- 1_7_4.137(w)/game/txt/register.txt Mon, 16 Jul 2001 12:18:30 -0500 dunemush (pennmush/24_register.t 1.1.2.1.1.1 600)
***************
*** 1,5 ****
  This message is shown when a user tries to create a player or register
  a player from a site that doesn't allow creation or registration,
! respectively. Alas. You'll probably have to send email to the
! person who runs this MUSH if you want a character.
  
--- 1,6 ----
  This message is shown when a user tries to create a player or register
  a player from a site that doesn't allow creation or registration,
! respectively, or if creation/registration is disabled entirely.
! Alas. You'll probably have to send email to the person who runs this
! MUSH if you want a character.
  
*** 1_7_4.130/game/restart Tue, 07 Nov 2000 13:23:41 -0600 dunemush (pennmush/39_restart 1.1.1.1.1.1.1.2.1.1.1.1.1.2 700)
--- 1_7_4.137(w)/game/restart Wed, 11 Jul 2001 10:51:10 -0500 dunemush (pennmush/39_restart 1.1.1.1.1.1.1.2.1.1.1.1.1.2.1.1 700)
***************
*** 59,65 ****
  
  
  if [ $mush -gt 0 ]; then
!   echo Mush already active.
    exit 0
  fi
  
--- 59,65 ----
  
  
  if [ $mush -gt 0 ]; then
!   echo Mush already active or some other process is using $CONF_FILE.
    exit 0
  fi
  
*** 1_7_4.130/src/wiz.c Sat, 07 Jul 2001 15:24:04 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.4 660)
--- 1_7_4.137(w)/src/wiz.c Wed, 25 Jul 2001 08:52:33 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.5 660)
***************
*** 106,123 ****
      return NOTHING;
    player = create_player(player_name, player_password, "None", "None");
    if (player == NOTHING) {
!     notify(creator,
! 	   tprintf(T("failure creating '%s' (bad name)"), player_name));
      return NOTHING;
    }
    if (player == AMBIGUOUS) {
!     notify(creator,
! 	   tprintf(T("failure creating '%s' (bad password)"), player_name));
      return NOTHING;
    }
!   notify(creator,
! 	 tprintf(T("New player '%s' (#%d) created with password '%s'"),
! 		 player_name, player, player_password));
    do_log(LT_WIZ, creator, player, T("Player creation"));
    return player;
  }
--- 106,121 ----
      return NOTHING;
    player = create_player(player_name, player_password, "None", "None");
    if (player == NOTHING) {
!     notify_format(creator, T("Failure creating '%s' (bad name)"), player_name);
      return NOTHING;
    }
    if (player == AMBIGUOUS) {
!     notify_format(creator, T("Failure creating '%s' (bad password)"),
! 		  player_name);
      return NOTHING;
    }
!   notify_format(creator, T("New player '%s' (#%d) created with password '%s'"),
! 		player_name, player, player_password);
    do_log(LT_WIZ, creator, player, T("Player creation"));
    return player;
  }
*** 1_7_4.130/src/predicat.c Mon, 18 Jun 2001 10:36:58 -0500 dunemush (pennmush/b/44_predicat.c 1.1.1.34.1.1.1.3.1.3 660)
--- 1_7_4.137(w)/src/predicat.c Wed, 25 Jul 2001 08:52:33 -0500 dunemush (pennmush/b/44_predicat.c 1.1.1.34.1.1.1.3.1.4 660)
***************
*** 596,601 ****
--- 596,604 ----
  
    const char *p;
  
+   if (!name || !*name)
+     return 0;
+ 
    /* No leading spaces */
    if (isspace(*name))
      return 0;
*** 1_7_4.130/src/parse.c Sat, 07 Jul 2001 21:06:09 -0500 dunemush (pennmush/b/48_parse.c 1.23.1.8 660)
--- 1_7_4.137(w)/src/parse.c Wed, 25 Jul 2001 08:52:32 -0500 dunemush (pennmush/b/48_parse.c 1.23.1.9 660)
***************
*** 41,46 ****
--- 41,49 ----
  extern int inum, inum_limit;
  int global_fun_invocations;
  int global_fun_recursions;
+ extern int re_subpatterns;
+ extern int *re_offsets;
+ extern char *re_from;
  
  struct debug_info {
    char *string;
***************
*** 294,299 ****
--- 297,303 ----
    active_table[','] = 1;
    active_table[';'] = 1;
    active_table['='] = 1;
+   active_table['$'] = 1;
  }
  
  #ifdef WIN32
***************
*** 451,456 ****
--- 455,490 ----
      }
  
      switch (**str) {
+     case '$':			/* Dollar subs for regedit() */
+       if ((eflags & (PE_DOLLAR | PE_EVALUATE)) != (PE_DOLLAR | PE_EVALUATE)) {
+ 	safe_chr('$', buff, bp);
+ 	(*str)++;
+       } else {
+ 	char obuf[BUFFER_LEN];
+ 	int p = 0;
+ 	char *o;
+ 
+ 	(*str)++;
+ 	/* Check the first two characters after the $ for a number */
+ 	if (isdigit(**str)) {
+ 	  p = **str - '0';
+ 	  (*str)++;
+ 	  if (isdigit(**str)) {
+ 	    p *= 10;
+ 	    p += **str - '0';
+ 	    (*str)++;
+ 	  }
+ 	} else
+ 	  break;
+ 
+ 	if (p > re_subpatterns || re_offsets == NULL || re_from == NULL)
+ 	  break;
+ 
+ 	pcre_copy_substring(re_from, re_offsets, re_subpatterns, p, obuf,
+ 			    BUFFER_LEN);
+ 	safe_str(obuf, buff, bp);
+       }
+       break;
      case '%':			/* Percent substitutions */
        if (!(eflags & PE_EVALUATE)) {
  	/* peak -- % escapes (at least) one character */
*** 1_7_4.130/src/info_slave.c Thu, 28 Sep 2000 12:37:49 -0500 dunemush (pennmush/c/7_info_slave 1.9 660)
--- 1_7_4.137(w)/src/info_slave.c Wed, 25 Jul 2001 08:52:32 -0500 dunemush (pennmush/c/7_info_slave 1.9.1.1 660)
***************
*** 107,113 ****
  #ifdef HAS_SOCKETPAIR
    mush = port;			/* We inherit open file descriptions and sockets from parent */
  #else
!   mush = make_socket_conn("127.0.0.1", NULL, 0, port, 0);
    if (mush == -1) {		/* Couldn't connect */
      fprintf(stderr, "Couldn't connect to mush!\n");
      exit(1);
--- 107,113 ----
  #ifdef HAS_SOCKETPAIR
    mush = port;			/* We inherit open file descriptions and sockets from parent */
  #else
!   mush = make_socket_conn("127.0.0.1", NULL, 0, port, NULL);
    if (mush == -1) {		/* Couldn't connect */
      fprintf(stderr, "Couldn't connect to mush!\n");
      exit(1);
*** 1_7_4.130/src/ident.c Wed, 14 Mar 2001 14:29:38 -0600 dunemush (pennmush/c/8_ident.c 1.19 660)
--- 1_7_4.137(w)/src/ident.c Wed, 25 Jul 2001 08:52:32 -0500 dunemush (pennmush/c/8_ident.c 1.19.1.2 660)
***************
*** 279,337 ****
      ((struct sockaddr_in6 *) &myinterface.addr)->sin6_port = 0;
  #endif
  
!   id->fd =
!     make_socket_conn(host, &myinterface.addr, llen, IDPORT,
! 		     timeout ? *timeout : 0);
  
!   if (id->fd < 0)		/* Couldn't connect to an ident server */
!     goto ERROR_BRANCH;
! 
!   if (timeout) {
!     time_t now, after;
! 
!     FD_ZERO(&rs);
!     FD_ZERO(&ws);
!     FD_ZERO(&es);
!     FD_SET(id->fd, &rs);
!     FD_SET(id->fd, &ws);
!     FD_SET(id->fd, &es);
!     to.tv_sec = *timeout;
!     to.tv_usec = 0;
!     now = time(NULL);
!     if ((res = select(id->fd + 1, &rs, &ws, &es, &to)) < 0) {
! #ifdef DEBUG
!       perror("libident: select");
! #endif
!       goto ERROR_BRANCH;
!     }
!     after = time(NULL);
!     *timeout -= after - now;
!     *timeout = *timeout < 0 ? 0 : *timeout;
! 
!     if (res == 0) {
! #ifndef WIN32
!       errno = ETIMEDOUT;
! #endif
!       goto ERROR_BRANCH;
!     }
!     if (FD_ISSET(id->fd, &es))
!       goto ERROR_BRANCH;
! 
!     if (!FD_ISSET(id->fd, &rs) && !FD_ISSET(id->fd, &ws))
!       goto ERROR_BRANCH;
!   }
!   return id;
! 
! ERROR_BRANCH:
! #ifndef WIN32
!   tmperrno = errno;		/* Save, so close() won't erase it */
! #endif
!   closesocket(id->fd);
!   free(id);
! #ifndef WIN32
!   errno = tmperrno;
! #endif
!   return 0;
  }
  
  
--- 279,291 ----
      ((struct sockaddr_in6 *) &myinterface.addr)->sin6_port = 0;
  #endif
  
!   id->fd = make_socket_conn(host, &myinterface.addr, llen, IDPORT, timeout);
  
!   if (id->fd < 0) {		/* Couldn't connect to an ident server */
!     free(id);
!     return NULL;
!   } else
!     return id;
  }
  
  
***************
*** 400,406 ****
      to.tv_sec = *timeout;
      to.tv_usec = 0;
      now = time(NULL);
!     if ((res = select(FD_SETSIZE, (fd_set *) 0, &ws, (fd_set *) 0, &to)) < 0)
        return -1;
      after = time(NULL);
      *timeout -= after - now;
--- 354,360 ----
      to.tv_sec = *timeout;
      to.tv_usec = 0;
      now = time(NULL);
!     if ((res = select(id->fd + 1, NULL, &ws, NULL, &to)) < 0)
        return -1;
      after = time(NULL);
      *timeout -= after - now;
***************
*** 418,424 ****
--- 372,382 ----
  #endif
  #endif				/* macintosh */
  
+ #ifdef WIN32
+   res = send(id->fd, buf, strlen(buf), 0);
+ #else
    res = write(id->fd, buf, strlen(buf));
+ #endif
  
  #ifndef macintosh
  #ifndef WIN32
***************
*** 525,531 ****
      to.tv_sec = *timeout;
      to.tv_usec = 0;
      now = time(NULL);
!     if ((res = select(FD_SETSIZE, &rs, (fd_set *) 0, (fd_set *) 0, &to)) < 0)
        return -1;
      after = time(NULL);
      *timeout -= after - now;
--- 483,489 ----
      to.tv_sec = *timeout;
      to.tv_usec = 0;
      now = time(NULL);
!     if ((res = select(id->fd + 1, &rs, NULL, NULL, &to)) < 0)
        return -1;
      after = time(NULL);
      *timeout -= after - now;
***************
*** 538,544 ****
      }
    }
    while (pos < sizeof(id->buf) &&
! 	 (res = read(id->fd, id->buf + pos, 1)) == 1 && id->buf[pos] != '\n')
      pos++;
    if (res < 0)
      return -1;
--- 496,507 ----
      }
    }
    while (pos < sizeof(id->buf) &&
! #ifdef WIN32
! 	 (res = recv(id->fd, id->buf + pos, 1, 0)) == 1
! #else
! 	 (res = read(id->fd, id->buf + pos, 1)) == 1
! #endif
! 	 && id->buf[pos] != '\n')
      pos++;
    if (res < 0)
      return -1;
*** 1_7_4.130/src/funlist.c Sat, 07 Jul 2001 21:06:09 -0500 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.2 660)
--- 1_7_4.137(w)/src/funlist.c Wed, 25 Jul 2001 08:52:31 -0500 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.3 660)
***************
*** 2376,2395 ****
   * patterns is faster than I thought it'd be, so this is low priority.
   */
  
! /* string, regexp, replacement string. Acts like sed or perl's s///,
!  * with version for i, g, and ig options. */
  FUNCTION(fun_regreplace)
  {
    pcre *re;
    pcre_extra *study = NULL;
    const char *errptr;
-   int erroffset;
-   int offsets[99];
    int subpatterns;
!   char *r, *start;
!   char tbuf[BUFFER_LEN];
!   char tmp;
!   int flags = 0, all = 0, match_offset = 0, len;
  
    if (!tables) {
      /* Initialize char tables so they match current locale. */
--- 2376,2399 ----
   * patterns is faster than I thought it'd be, so this is low priority.
   */
  
! /* string, regexp, replacement string. Acts like sed or perl's s///g,
! //with an ig version */
! int re_subpatterns = -1;
! int *re_offsets;
! char *re_from = NULL;
  FUNCTION(fun_regreplace)
  {
    pcre *re;
    pcre_extra *study = NULL;
    const char *errptr;
    int subpatterns;
!   int offsets[99];
!   int erroffset;
!   const char *r, *obp;
!   char *start, *oldbp;
!   char tbuf[BUFFER_LEN], *tbp;
!   char abuf[BUFFER_LEN], *abp;
!   int flags = 0, all = 0, match_offset = 0, len, funccount;
  
    if (!tables) {
      /* Initialize char tables so they match current locale. */
***************
*** 2402,2408 ****
    if (string_prefix(called_as, "REGEDITALL"))
      all = 1;
  
!   if ((re = pcre_compile(args[1], flags, &errptr, &erroffset, tables)) == NULL) {
      /* Matching error. */
      safe_str(T("#-1 REGEXP ERROR: "), buff, bp);
      safe_str(errptr, buff, bp);
--- 2406,2423 ----
    if (string_prefix(called_as, "REGEDITALL"))
      all = 1;
  
!   tbp = tbuf;
!   r = args[1];
!   process_expression(tbuf, &tbp, &r, executor, caller, enactor, PE_DEFAULT,
! 		     PT_DEFAULT, pe_info);
!   *tbp = '\0';
!   abp = abuf;
!   r = args[0];
!   process_expression(abuf, &abp, &r, executor, caller, enactor, PE_DEFAULT,
! 		     PT_DEFAULT, pe_info);
!   *abp = '\0';
! 
!   if ((re = pcre_compile(tbuf, flags, &errptr, &erroffset, tables)) == NULL) {
      /* Matching error. */
      safe_str(T("#-1 REGEXP ERROR: "), buff, bp);
      safe_str(errptr, buff, bp);
***************
*** 2426,2484 ****
        add_check("pcre.extra");
  #endif
    }
!   len = strlen(args[0]);
!   start = args[0];
!   subpatterns = pcre_exec(re, study, args[0], len, 0, 0, offsets, 99);
  
    /* Match wasn't found... we're done */
    if (subpatterns < 0) {
!     safe_str(args[0], buff, bp);
      mush_free((Malloc_t) re, "pcre");
      if (study)
        mush_free((Malloc_t) study, "pcre.extra");
      return;
    }
  
    do {
      /* Copy up to the start of the matched area */
!     tmp = args[0][offsets[0]];
!     args[0][offsets[0]] = '\0';
      safe_str(start, buff, bp);
!     args[0][offsets[0]] = tmp;
  
      /* Now copy in the replacement, putting in captured sub-expressions */
!     for (r = args[2]; *r; r++) {
!       int offset;
!       char *endsub;
! 
!       if (*r != '$') {
! 	safe_chr(*r, buff, bp);
! 	continue;
!       }
!       r++;
!       offset = strtoul(r, &endsub, 10);
!       /* Not a valid number */
!       if (r == endsub) {
! 	safe_chr('$', buff, bp);
! 	r--;
! 	continue;
!       }
!       r = endsub - 1;
!       if (offset >= subpatterns)
! 	continue;
! 
!       pcre_copy_substring(args[0], offsets, subpatterns, offset,
! 			  tbuf, BUFFER_LEN);
!       safe_str(tbuf, buff, bp);
  
!     }
!     start = args[0] + offsets[1];
      match_offset = offsets[1];
      /* Make sure we advance at least 1 char */
      if (offsets[0] == match_offset)
        match_offset++;
    } while (all && match_offset < len && (subpatterns =
! 					 pcre_exec(re, study, args[0], len,
  						   match_offset, 0, offsets,
  						   99)) >= 0);
  
--- 2441,2488 ----
        add_check("pcre.extra");
  #endif
    }
!   len = strlen(abuf);
!   start = abuf;
!   subpatterns = pcre_exec(re, study, abuf, len, 0, 0, offsets, 99);
  
    /* Match wasn't found... we're done */
    if (subpatterns < 0) {
!     safe_str(abuf, buff, bp);
      mush_free((Malloc_t) re, "pcre");
      if (study)
        mush_free((Malloc_t) study, "pcre.extra");
      return;
    }
  
+   funccount = pe_info->fun_invocations;
+   oldbp = *bp;
+ 
    do {
      /* Copy up to the start of the matched area */
!     char tmp = abuf[offsets[0]];
!     abuf[offsets[0]] = '\0';
      safe_str(start, buff, bp);
!     abuf[offsets[0]] = tmp;
  
      /* Now copy in the replacement, putting in captured sub-expressions */
!     obp = args[2];
!     re_from = abuf;
!     re_offsets = offsets;
!     re_subpatterns = subpatterns;
!     process_expression(buff, bp, &obp, executor, caller, enactor,
! 		       PE_DEFAULT | PE_DOLLAR, PT_DEFAULT, pe_info);
!     if (*bp == oldbp && pe_info->fun_invocations == funccount)
!       break;
!     oldbp = *bp;
!     funccount = pe_info->fun_invocations;
  
!     start = abuf + offsets[1];
      match_offset = offsets[1];
      /* Make sure we advance at least 1 char */
      if (offsets[0] == match_offset)
        match_offset++;
    } while (all && match_offset < len && (subpatterns =
! 					 pcre_exec(re, study, abuf, len,
  						   match_offset, 0, offsets,
  						   99)) >= 0);
  
***************
*** 2489,2494 ****
--- 2493,2502 ----
    mush_free((Malloc_t) re, "pcre");
    if (study)
      mush_free((Malloc_t) study, "pcre.extra");
+ 
+   re_offsets = NULL;
+   re_subpatterns = -1;
+   re_from = NULL;
  }
  
  
*** 1_7_4.130/src/fundb.c Tue, 03 Jul 2001 13:25:37 -0500 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.2 660)
--- 1_7_4.137(w)/src/fundb.c Wed, 25 Jul 2001 08:52:31 -0500 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.3 660)
***************
*** 1443,1449 ****
    if (nargs == 2)
      cost = parse_integer(args[1]);
    else
!     cost = 10;
    safe_dbref(do_create(executor, args[0], cost), buff, bp);
  }
  
--- 1443,1449 ----
    if (nargs == 2)
      cost = parse_integer(args[1]);
    else
!     cost = OBJECT_COST;
    safe_dbref(do_create(executor, args[0], cost), buff, bp);
  }
  
*** 1_7_4.130/src/function.c Sat, 07 Jul 2001 21:06:09 -0500 dunemush (pennmush/c/18_function.c 1.29.1.14.1.3.1.4 660)
--- 1_7_4.137(w)/src/function.c Wed, 25 Jul 2001 08:52:31 -0500 dunemush (pennmush/c/18_function.c 1.29.1.14.1.3.1.5 660)
***************
*** 373,382 ****
  #endif
    {"R", fun_r, 1, 1, FN_REG},
    {"RAND", fun_rand, 1, 1, FN_REG},
!   {"REGEDIT", fun_regreplace, 3, 3, FN_REG},
!   {"REGEDITALL", fun_regreplace, 3, 3, FN_REG},
!   {"REGEDITALLI", fun_regreplace, 3, 3, FN_REG},
!   {"REGEDITI", fun_regreplace, 3, 3, FN_REG},
    {"REGMATCH", fun_regmatch, 2, 3, FN_REG},
    {"REGMATCHI", fun_regmatch, 2, 3, FN_REG},
    {"REGRAB", fun_regrab, 2, 3, FN_REG},
--- 373,382 ----
  #endif
    {"R", fun_r, 1, 1, FN_REG},
    {"RAND", fun_rand, 1, 1, FN_REG},
!   {"REGEDIT", fun_regreplace, 3, 3, FN_NOPARSE},
!   {"REGEDITALL", fun_regreplace, 3, 3, FN_NOPARSE},
!   {"REGEDITALLI", fun_regreplace, 3, 3, FN_NOPARSE},
!   {"REGEDITI", fun_regreplace, 3, 3, FN_NOPARSE},
    {"REGMATCH", fun_regmatch, 2, 3, FN_REG},
    {"REGMATCHI", fun_regmatch, 2, 3, FN_REG},
    {"REGRAB", fun_regrab, 2, 3, FN_REG},
*** 1_7_4.130/src/flags.c Mon, 18 Jun 2001 10:36:58 -0500 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.1 660)
--- 1_7_4.137(w)/src/flags.c Wed, 25 Jul 2001 08:52:31 -0500 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.2 660)
***************
*** 119,125 ****
    {"FORCE_WHITE", 'f', TYPE_PLAYER, PLAYER_FORCEWHITE, F_ANY, F_ANY},
  
    {"MONITOR", 'M', TYPE_PLAYER, PLAYER_MONITOR, F_ROYAL, F_ANY},
!   {"NOSPOOF", 'N', TYPE_PLAYER, PLAYER_NOSPOOF, F_ANY, F_ANY},
    {"ZONE", 'Z', TYPE_PLAYER, PLAYER_ZONE, F_ANY, F_ANY},
    {"CONNECTED", 'c', TYPE_PLAYER, PLAYER_CONNECT, F_INTERNAL | F_MDARK,
     F_INTERNAL | F_MDARK},
--- 119,126 ----
    {"FORCE_WHITE", 'f', TYPE_PLAYER, PLAYER_FORCEWHITE, F_ANY, F_ANY},
  
    {"MONITOR", 'M', TYPE_PLAYER, PLAYER_MONITOR, F_ROYAL, F_ANY},
!   {"NOSPOOF", 'N', TYPE_PLAYER, PLAYER_NOSPOOF, F_ANY | F_ODARK,
!    F_ANY | F_ODARK},
    {"ZONE", 'Z', TYPE_PLAYER, PLAYER_ZONE, F_ANY, F_ANY},
    {"CONNECTED", 'c', TYPE_PLAYER, PLAYER_CONNECT, F_INTERNAL | F_MDARK,
     F_INTERNAL | F_MDARK},
*** 1_7_4.130/src/bsd.c Mon, 09 Jul 2001 09:04:12 -0500 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.7 660)
--- 1_7_4.137(w)/src/bsd.c Wed, 25 Jul 2001 08:52:30 -0500 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.9 660)
***************
*** 3759,3765 ****
        return 0;
      }
      if (!options.login_allow || !options.create_allow) {
!       fcache_dump(d, options.down_fcache);
        do_rawlog(LT_CONN,
  		"REFUSED CREATION for %s from %s on descriptor %d.\n",
  		user, d->addr, d->descriptor);
--- 3759,3768 ----
        return 0;
      }
      if (!options.login_allow || !options.create_allow) {
!       if (!options.login_allow)
! 	fcache_dump(d, options.down_fcache);
!       else
! 	fcache_dump(d, options.register_fcache);
        do_rawlog(LT_CONN,
  		"REFUSED CREATION for %s from %s on descriptor %d.\n",
  		user, d->addr, d->descriptor);
***************
*** 3803,3809 ****
        return 0;
      }
      if (!options.create_allow) {
!       fcache_dump(d, options.down_fcache);
        do_rawlog(LT_CONN,
  		"Refused registration (creation disabled) for %s from %s on descriptor %d.\n",
  		user, d->addr, d->descriptor);
--- 3806,3812 ----
        return 0;
      }
      if (!options.create_allow) {
!       fcache_dump(d, options.register_fcache);
        do_rawlog(LT_CONN,
  		"Refused registration (creation disabled) for %s from %s on descriptor %d.\n",
  		user, d->addr, d->descriptor);
***************
*** 4870,4894 ****
  inactivity_check()
  {
    DESC *d, *nextd;
!   register struct tm *idle;
!   time_t now;
!   int check, hrs, mns;
  
    if (!INACTIVITY_LIMIT)
      return;
  
-   check = hrs = mns = 0;
    now = mudtime;
! 
!   for (mns = INACTIVITY_LIMIT; mns > 60; mns -= 60, hrs++) ;
  
    for (d = descriptor_list; d; d = nextd) {
      nextd = d->next;
!     check = (now - d->last_time);
!     idle = gmtime((time_t *) & check);
! 
!     if ((idle->tm_hour > hrs) ||
! 	((idle->tm_hour == hrs) && (idle->tm_min >= mns))) {
  
        if (!d->connected)
  	shutdownsock(d);
--- 4873,4889 ----
  inactivity_check()
  {
    DESC *d, *nextd;
!   time_t now, idle;
  
    if (!INACTIVITY_LIMIT)
      return;
  
    now = mudtime;
!   idle = INACTIVITY_LIMIT * 60;
  
    for (d = descriptor_list; d; d = nextd) {
      nextd = d->next;
!     if ((now - d->last_time) > idle) {
  
        if (!d->connected)
  	shutdownsock(d);
*** 1_7_4.130/src/attrib.c Mon, 18 Jun 2001 10:36:58 -0500 dunemush (pennmush/c/40_attrib.c 1.15.1.2.1.5.1.1.1.3.1.3.1.2.1.2.1.2.2.1.1.1 660)
--- 1_7_4.137(w)/src/attrib.c Wed, 25 Jul 2001 08:52:29 -0500 dunemush (pennmush/c/40_attrib.c 1.15.1.2.1.5.1.1.1.3.1.3.1.2.1.2.1.2.2.1.1.2 660)
***************
*** 901,907 ****
      if (old) {
        /* Old alias - we're allowed to change to a different case */
        strcpy(tbuf1, uncompress(AL_STR(old)));
!       if (s && *s && strcasecmp(s, tbuf1) && !ok_player_name(s)) {
  	notify(player, T("That is not a valid alias."));
  	return -1;
        }
--- 901,907 ----
      if (old) {
        /* Old alias - we're allowed to change to a different case */
        strcpy(tbuf1, uncompress(AL_STR(old)));
!       if (s && (!*s || (strcasecmp(s, tbuf1) && !ok_player_name(s)))) {
  	notify(player, T("That is not a valid alias."));
  	return -1;
        }
*** 1_7_4.130/hdrs/version.h Mon, 02 Jul 2001 10:18:36 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.6 660)
--- 1_7_4.137(w)/hdrs/version.h Wed, 25 Jul 2001 08:52:34 -0500 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.6 660)
***************
*** 1,2 ****
! #define VERSION "PennMUSH version 1.7.4 patchlevel 7 [07/02/2001]"
! #define SHORTVN "PennMUSH 1.7.4p7"
--- 1,2 ----
! #define VERSION "PennMUSH version 1.7.4 patchlevel 8 [07/22/2001]"
! #define SHORTVN "PennMUSH 1.7.4p8"
*** 1_7_4.130/hdrs/parse.h Sat, 07 Jul 2001 21:06:09 -0500 dunemush (pennmush/c/51_parse.h 1.9 660)
--- 1_7_4.137(w)/hdrs/parse.h Wed, 25 Jul 2001 08:52:34 -0500 dunemush (pennmush/c/51_parse.h 1.10 660)
***************
*** 188,193 ****
--- 188,194 ----
  #define PE_FUNCTION_CHECK       0x00000020
  #define PE_FUNCTION_MANDATORY   0x00000040
  #define PE_LITERAL              0x00000100
+ #define PE_DOLLAR               0x00000200
  
  #define PE_DEFAULT (PE_COMPRESS_SPACES | PE_STRIP_BRACES | \
                      PE_EVALUATE | PE_FUNCTION_CHECK)
*** 1_7_4.130/hdrs/mysocket.h Fri, 11 May 2001 15:40:56 -0500 dunemush (pennmush/e/51_mysocket.h 1.8 660)
--- 1_7_4.137(w)/hdrs/mysocket.h Wed, 25 Jul 2001 08:52:34 -0500 dunemush (pennmush/e/51_mysocket.h 1.9 660)
***************
*** 70,79 ****
  _((Port_t port, union sockaddr_u * addr, socklen_t *len, const char *host));
  /* Connect somewhere */
  int make_socket_conn _((const char *host, struct sockaddr * myiterface,
! 			socklen_t myilen, Port_t port, int timeout));
  void make_nonblocking _((int s));
  int connect_nonb
! _((int sockfd, const struct sockaddr * saptr, socklen_t salen, int nsec));
  /* Win32 uses closesocket() to close a socket, and so will we */
  #ifndef WIN32
  #define closesocket(s)  close(s)
--- 70,79 ----
  _((Port_t port, union sockaddr_u * addr, socklen_t *len, const char *host));
  /* Connect somewhere */
  int make_socket_conn _((const char *host, struct sockaddr * myiterface,
! 			socklen_t myilen, Port_t port, int *timeout));
  void make_nonblocking _((int s));
  int connect_nonb
! _((int sockfd, const struct sockaddr * saptr, socklen_t salen, int *nsec));
  /* Win32 uses closesocket() to close a socket, and so will we */
  #ifndef WIN32
  #define closesocket(s)  close(s)
*** 1_7_4.130/src/mysocket.c Tue, 15 May 2001 15:59:50 -0500 dunemush (pennmush/f/0_mysocket.c 1.16.1.1.1.1.1.1.1.4.1.1 660)
--- 1_7_4.137(w)/src/mysocket.c Wed, 25 Jul 2001 08:52:32 -0500 dunemush (pennmush/f/0_mysocket.c 1.16.1.1.1.1.1.1.1.4.1.3 660)
***************
*** 146,152 ****
  #ifdef CAN_NEWSTYLE
  int
  make_socket_conn(const char *host, struct sockaddr *myiterface,
! 		 socklen_t myilen, Port_t port, int timeout)
  #else
  int
  make_socket_conn(host, myiterface, myilen, port, timeout)
--- 146,152 ----
  #ifdef CAN_NEWSTYLE
  int
  make_socket_conn(const char *host, struct sockaddr *myiterface,
! 		 socklen_t myilen, Port_t port, int *timeout)
  #else
  int
  make_socket_conn(host, myiterface, myilen, port, timeout)
***************
*** 154,160 ****
      struct sockaddr *myiterface;
      socklen_t myilen;
      Port_t port;
!     int timeout;
  #endif
  {
    struct addrinfo hints, *server, *save;
--- 154,160 ----
      struct sockaddr *myiterface;
      socklen_t myilen;
      Port_t port;
!     int *timeout;
  #endif
  {
    struct addrinfo hints, *server, *save;
***************
*** 210,228 ****
  
    freeaddrinfo(save);
  
- #ifdef DEBUG
    if (server == NULL) {
! #else
!   /* Usually, we don't want to show this for failed connect to
!    * an ident server, as that just means they're not running one
!    */
!   if (server == NULL && port != IDPORT) {
  #endif
-     fprintf(stderr, "Couldn't connect to %s on port %hu\n", host, port);
-     fflush(stderr);
      return -1;
    }
-   fflush(stderr);
    return s;
  }
  
--- 210,230 ----
  
    freeaddrinfo(save);
  
    if (server == NULL) {
! #ifndef DEBUG
!     /* Usually, we don't want to show this for failed connect to
!      * an ident server, as that just means they're not running one
!      */
! 
!     if (port != IDPORT) {
! #endif
!       fprintf(stderr, "Couldn't connect to %s on port %hu\n", host, port);
!       fflush(stderr);
! #ifndef DEBUG
!     }
  #endif
      return -1;
    }
    return s;
  }
  
***************
*** 359,414 ****
  
  	   Returns 0 on success, -1 on failure. */
  int
! connect_nonb(sockfd, saptr, salen, nsec)
      int sockfd;
      const struct sockaddr *saptr;
      socklen_t salen;
!     int nsec;
  {
    int n, error;
    socklen_t len;
    fd_set rset, wset;
    struct timeval tval;
  
!   if (nsec)
      make_nonblocking(sockfd);
  
    error = 0;
    if ((n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
      if (errno != EINPROGRESS)
!       return (-1);
  
    /* connect completed immediately or we did a blocking connect  */
!   if (!nsec || n == 0)
      goto done;
  
    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);
    wset = rset;
!   tval.tv_sec = nsec;
    tval.tv_usec = 0;
  
!   if ((n = select(sockfd + 1, &rset, &wset, NULL, nsec ? &tval : NULL)) == 0) {
!     close(sockfd);		/* timeout */
      errno = ETIMEDOUT;
!     return (-1);
    }
  
    if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
      len = sizeof(error);
      if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (__ptr_t) &error, &len) < 0)
!       return (-1);		/* Solaris pending error */
    } else
      return -1;
  
  done:
  
    if (error) {
!     close(sockfd);		/* just in case */
      errno = error;
!     return (-1);
    }
!   return (0);
  }
  
  
--- 361,426 ----
  
  	   Returns 0 on success, -1 on failure. */
  int
! connect_nonb(sockfd, saptr, salen, timeout)
      int sockfd;
      const struct sockaddr *saptr;
      socklen_t salen;
!     int *timeout;
  {
    int n, error;
+   time_t start, end;
    socklen_t len;
    fd_set rset, wset;
    struct timeval tval;
  
!   if (timeout && *timeout)
      make_nonblocking(sockfd);
  
    error = 0;
    if ((n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
+ #ifdef WIN32
+     if (n == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
+ #else
      if (errno != EINPROGRESS)
! #endif
!       return -1;
  
    /* connect completed immediately or we did a blocking connect  */
!   if (!timeout || !*timeout || n == 0)
      goto done;
  
    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);
    wset = rset;
!   tval.tv_sec = *timeout;
    tval.tv_usec = 0;
+   time(&start);
  
!   if ((n = select(sockfd + 1, &rset, &wset, NULL, &tval)) == 0) {
!     closesocket(sockfd);	/* timeout */
      errno = ETIMEDOUT;
!     return -1;
    }
  
+   time(&end);
+   *timeout -= end - start;
+   *timeout = *timeout < 0 ? 0 : *timeout;
+ 
    if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
      len = sizeof(error);
      if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (__ptr_t) &error, &len) < 0)
!       return -1;		/* Solaris pending error */
    } else
      return -1;
  
  done:
  
    if (error) {
!     closesocket(sockfd);	/* just in case */
      errno = error;
!     return -1;
    }
!   return 0;
  }