diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/conf/version.def wfdb-10.3.9/conf/version.def
--- wfdb-10.3.8/conf/version.def	2003-06-05 23:07:49.000000000 -0400
+++ wfdb-10.3.9/conf/version.def	2003-07-16 20:07:09.000000000 -0400
@@ -1,10 +1,10 @@
 # file: version.def		G. Moody	24 May 2000
-#				Last revised:   5 June 2003
+#				Last revised:	16 July 2003
 # Each release of the WFDB Software Package is identified by a three-part
 # version number, defined here:
 MAJOR = 10
 MINOR = 3
-RELEASE = 8
+RELEASE = 9
 VERSION = $(MAJOR).$(MINOR).$(RELEASE)
 
 # RPMRELEASE can be incremented if changes are made between official
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/doc/wpg-src/wpg0.tex wfdb-10.3.9/doc/wpg-src/wpg0.tex
--- wfdb-10.3.8/doc/wpg-src/wpg0.tex	2003-07-12 02:43:58.000000000 -0400
+++ wfdb-10.3.9/doc/wpg-src/wpg0.tex	2003-07-16 22:28:51.000000000 -0400
@@ -488,6 +488,23 @@
 WFDB Software Package distribution, for information on any more recent
 changes that may not be described here.
 
+@unnumberedsubsec Changes in version 10.3.9
+
+The WFDB library functions @code{setwfdb}, @code{setannstr},
+@code{setanndesc}, and @code{setecgstr} now copy their input string
+arguments, so that it is no longer necessary for WFDB applications to
+keep these strings valid.  If you have created applications that rely on
+being able to modify these strings, it will be necessary to invoke the
+corresponding functions again before such changes will take effect
+within the WFDB library.
+
+Previous versions of the WFDB library function @code{putinfo} did not
+flush their output until either a new header file was created (via
+@code{setheader} or @code{newheader}) or the process exited.  This has
+now been corrected, and putinfo output is now flushed before
+@code{putinfo} returns.  Thanks to Jonas Carlson for reporting this
+problem.
+
 @unnumberedsubsec Changes in version 10.3.8
 
 The WFDB library function @code{setbasetime()} now properly
@@ -2765,8 +2782,7 @@
 strings for undefined annotation codes.  For example,
 @code{setannstr(NORMAL, "\\267")} redefines the string for normal beats
 as a PostScript bullet, @samp{@bullet{}} (@code{NORMAL} is defined in
-@file{<wfdb/ecgcodes.h>}).  These functions do not copy their string
-arguments, which must therefore be kept valid by the caller.
+@file{<wfdb/ecgcodes.h>}).
 
 @cindex modification label
 An important difference between @code{setannstr} (or @code{setanndesc})
@@ -3928,15 +3944,6 @@
 an input file (e.g., using @code{annopen} or @code{isigopen}).  (The
 features described in this paragraph were first introduced in WFDB library
 version 8.0.)
-
-The @code{setwfdb} function does not copy the string itself, which must
-therefore be kept valid by the caller, nor does it modify the environment
-variable @code{WFDB}, which will be inherited by any processes spawned
-from the caller.  For portability, as well as efficiency, it is better
-to use @code{setwfdb} than to manipulate @code{WFDB} directly (via
-@code{putenv}, for example); furthermore, doing the latter is
-ineffective (within the current process) once the first WFDB file has been
-opened.
 @iftex
 @xref{getwfdb, , @code{getwfdb}},
 @end iftex
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/lib/annot.c wfdb-10.3.9/lib/annot.c
--- wfdb-10.3.8/lib/annot.c	2002-07-20 22:29:09.000000000 -0400
+++ wfdb-10.3.9/lib/annot.c	2003-07-16 20:10:04.000000000 -0400
@@ -1,10 +1,10 @@
 /* file: annot.c	G. Moody       	 13 April 1989
-			Last revised:    20 July 2002		wfdblib 10.2.7
+			Last revised:    16 July 2003		wfdblib 10.3.9
 WFDB library functions for annotations
 
 _______________________________________________________________________________
 wfdb: a library for reading and writing annotated waveforms (time series data)
-Copyright (C) 2002 George B. Moody
+Copyright (C) 2003 George B. Moody
 
 This library is free software; you can redistribute it and/or modify it under
 the terms of the GNU Library General Public License as published by the Free
@@ -694,7 +694,10 @@
 char *string;
 {
     if (NOTQRS <= code && code <= ACMAX) {
-	cstring[code] = string;
+	if (strcmp(cstring[code], string)) {
+	    char *p = malloc(strlen(string)+1);
+	    if (p) strcpy(cstring[code] = p, string);
+	}
 	return (0);
     }
     wfdb_error("setecgstr: illegal annotation code %d\n", code);
@@ -743,12 +746,20 @@
 char *string;
 {
     if (0 < code && code <= ACMAX) {
-	astring[code] = string;
-	modified[code] = 1;
+	if (strcmp(astring[code], string)) {
+	    char *p = malloc(strlen(string)+1);
+	    if (p) {
+		strcpy(astring[code] = p, string);
+		modified[code] = 1;
+	    }
+	}
 	return (0);
     }
     else if (-ACMAX < code && code <= 0) {
-	astring[-code] = string;
+	if (strcmp(astring[-code], string)) {
+	    char *p = malloc(strlen(string)+1);
+	    if (p) strcpy(astring[-code] = p, string);
+	}
 	return (0);
     }
     else {
@@ -824,12 +835,20 @@
 char *string;
 {
     if (0 < code && code <= ACMAX) {
-	tstring[code] = string;
-	modified[code] = 1;
+	if (strcmp(tstring[code], string)) {
+	    char *p = malloc(strlen(string)+1);
+	    if (p) {
+		strcpy(tstring[code] = p, string);
+		modified[code] = 1;
+	    }
+	}
 	return (0);
     }
     else if (-ACMAX < code && code <= 0) {
-	tstring[-code] = string;
+	if (strcmp(tstring[-code], string)) {
+	    char *p = malloc(strlen(string)+1);
+	    if (p) strcpy(tstring[-code] = p, string);
+	}
 	return (0);
     }
     else {
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/lib/signal.c wfdb-10.3.9/lib/signal.c
--- wfdb-10.3.8/lib/signal.c	2003-07-09 14:14:52.000000000 -0400
+++ wfdb-10.3.9/lib/signal.c	2003-07-16 22:09:16.000000000 -0400
@@ -1,5 +1,5 @@
 /* file: signal.c	G. Moody	13 April 1989
-			Last revised:    9 July 2003		wfdblib 10.3.8
+			Last revised:   16 July 2003		wfdblib 10.3.9
 WFDB library functions for signals
 
 _______________________________________________________________________________
@@ -2500,6 +2500,7 @@
 	return (-1);
     }
     (void)wfdb_fprintf(oheader, "#%s\r\n", s);
+    (void)wfdb_fflush(oheader);
     return (0);
 }
 
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/lib/wfdb.h0 wfdb-10.3.9/lib/wfdb.h0
--- wfdb-10.3.8/lib/wfdb.h0	2003-07-09 13:29:20.000000000 -0400
+++ wfdb-10.3.9/lib/wfdb.h0	2003-07-16 20:07:06.000000000 -0400
@@ -1,5 +1,5 @@
 /* file: wfdb.h		G. Moody	13 June 1983
-			Last revised:    9 July 2003	wfdblib 10.3.8
+			Last revised:   16 July 2003	wfdblib 10.3.9
 WFDB library type, constant, structure, and function interface definitions
 
 _______________________________________________________________________________
@@ -33,7 +33,7 @@
 /* WFDB library version. */
 #define WFDB_MAJOR   10
 #define WFDB_MINOR   3
-#define WFDB_RELEASE 8
+#define WFDB_RELEASE 9
 #define WFDB_NETFILES 1	/* if 1, library includes code for HTTP, FTP clients */
 
 /* Determine what type of compiler is being used. */
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/lib/wfdbio.c wfdb-10.3.9/lib/wfdbio.c
--- wfdb-10.3.8/lib/wfdbio.c	2003-04-01 18:24:47.000000000 -0500
+++ wfdb-10.3.9/lib/wfdbio.c	2003-07-16 21:38:30.000000000 -0400
@@ -1,5 +1,5 @@
 /* file: wfdbio.c	G. Moody	18 November 1988
-			Last revised:	  1 April 2003		wfdblib 10.3.6
+			Last revised:	  16 July 2003		wfdblib 10.3.9
 Low-level I/O functions for the WFDB library
 
 _______________________________________________________________________________
@@ -48,6 +48,7 @@
  wfdb_p32		(writes a 32-bit integer)
  wfdb_free_path_list *** (frees all data structures assigned to the path list)
  wfdb_parse_path ***	(splits WFDB path into components)
+ wfdb_export_config **** (puts the WFDB path, etc. into the environment)
  wfdb_getiwfdb *	(sets WFDB from the contents of a file)
  wfdb_addtopath *	(adds path component of string argument to WFDB path)
  wfdb_error		(produces an error message)
@@ -56,7 +57,8 @@
  wfdb_checkname		(checks record and annotator names for validity)
  wfdb_setirec **	(saves current record name)
 
-(* New in version 6.2; ** new in version 9.7; *** new in version 10.0.1)
+(* New in version 6.2; ** new in version 9.7; *** new in version 10.0.1;
+**** new in version 10.3.9)
 
 The next two groups of functions, which together enable input from remote
 (http and ftp) files, were first implemented in version 10.0.1 by Michael
@@ -147,79 +149,42 @@
 
 /* WFDB library functions */
 
-/* getwfdb is used to obtain a list of places in which to search for database
-files to be opened for reading.  Under UNIX or MS-DOS, this list is obtained
-from the shell (environment) variable WFDB, which may be set by the user
-(typically as part of the login script).  A default value may be set at compile
-time (DEFWFDB in wfdblib.h);  this is necessary when compiling for the
-Macintosh OS.  If the value of WFDB is of the form `@FILE', wfdb_getiwfdb()
-reads the WFDB path from the specified FILE. */
+/* getwfdb is used to obtain the WFDB path, a list of places in which to search
+for database files to be opened for reading.  In most environments, this list
+is obtained from the shell (environment) variable WFDB, which may be set by the
+user (typically as part of the login script).  A default value may be set at
+compile time (DEFWFDB in wfdblib.h); this is necessary for environments that do
+not support the concept of environment variables, such as MacOS9 and earlier.
+If WFDB or DEFWFDB is of the form '@FILE', getwfdb reads the WFDB path from the
+specified (local) FILE (using wfdb_getiwfdb); such files may be nested up to
+10 levels. */
 
 static char *wfdbpath;
-static int getiwfdb_count = 0;
 
 FSTRING getwfdb()
 {
-    void wfdb_getiwfdb();
-
     if (wfdbpath == NULL) {
-	wfdbpath = getenv("WFDB");
-	if (wfdbpath == NULL) {
-#ifdef HAS_PUTENV
-	    static char *p;
-	    if (p == NULL) p = (char *)malloc(strlen(DEFWFDB)+6);
-	    if (p) {
-		sprintf(p, "WFDB=%s", DEFWFDB);
-		putenv(p);
-	    }
-#endif
-	    wfdbpath = DEFWFDB;
-	}
-    }
-    getiwfdb_count = 0;
-    while (*wfdbpath == '@')
-	wfdb_getiwfdb();
-    wfdb_parse_path(wfdbpath);
-#ifdef HAS_PUTENV
-    if (getenv("WFDBCAL") == NULL) {
-	static char *p;
-	if (p == NULL) p = malloc(strlen(DEFWFDBCAL)+9);
-	if (p) {
-	    sprintf(p, "WFDBCAL=%s", DEFWFDBCAL);
-	    putenv(p);
-	}
-    }
-    if (getenv("WFDBANNSORT") == NULL) {
-	static char *p;
-	if (p == NULL) p = malloc(32);
-	if (p) {
-	    sprintf(p, "WFDBANNSORT=%d", DEFWFDBANNSORT);
-	    putenv(p);
-	}
-    }
-    if (getenv("WFDBGVMODE") == NULL) {
-	static char *p;
-	if (p == NULL) p = malloc(32);
-	if (p) {
-	    sprintf(p, "WFDBGVMODE=%d", DEFWFDBGVMODE == 0 ? 0 : 1);
-	    putenv(p);
-	}
-    }
+	char *p = getenv("WFDB"), *wfdb_getiwfdb();
 
-
-#endif
+	if (p == NULL) p = DEFWFDB;
+	if (*p == '@') p = wfdb_getiwfdb();
+	setwfdb(p);
+    }
     return (wfdbpath);
 }
 
-/* setwfdb can be called within an application to override the setting of WFDB.
-For portability, as well as efficiency, it is better to use setwfdb() than
-to manipulate WFDB directly (via putenv(), for example.) */
+/* setwfdb can be called within an application to change the WFDB path. */
 
-FVOID setwfdb(pt)
-char *pt;
+FVOID setwfdb(p)
+char *p;
 {
-   wfdbpath = pt;
-   wfdb_parse_path(wfdbpath);
+    void wfdb_export_config();
+
+    if (p == NULL && (p = getenv("WFDB")) == NULL) p = DEFWFDB;
+    wfdb_parse_path(p);
+    if (wfdbpath = (char *)malloc(strlen(p)+1))
+	strcpy(wfdbpath, p);
+    wfdb_export_config();
 }
 
 /* wfdbquiet can be used to suppress error messages from the WFDB library. */
@@ -241,6 +206,8 @@
 #define MFNLEN	256	/* max length of WFDB filename, including '\0' */
 static char wfdb_filename[MFNLEN];
 
+/* wfdbfile returns the pathname or URL of a WFDB file. */
+
 FSTRING wfdbfile(s, record)
 char *s, *record;
 {
@@ -331,29 +298,29 @@
 /* Operating system and compiler dependent code
 
 All of the operating system and compiler dependencies in the WFDB library are
-contained within the following section of this file.
+contained within the following section of this file.  (In the following
+comments, 'MS-DOS' includes all versions of MS-Windows.)
 
 1. Directory separators vary:
      UNIX and variants use `/'.
      MS-DOS and OS/2 use `\'.
-     Macintosh OS uses `:'.
+     MacOS uses `:'.
 
 2. Path component separators also vary:
      UNIX and variants use `:' (as in the PATH environment variable)
      MS-DOS and OS/2 use `;' (also as in the PATH environment variable;
        `:' within a path component follows a drive letter)
-     Macintosh OS uses `;' (`:' is a directory separator, as noted above)
+     MacOS uses `;' (`:' is a directory separator, as noted above)
    See the notes above wfdb_open for details about path separators and how
    WFDB file names are constructed.
 
 3. By default, MS-DOS files are opened in "text" mode.  Since WFDB files are
    binary, they must be opened in binary mode.  To accomplish this, ANSI C
-   libraries, and those supplied with non-ANSI C compilers under MS-DOS,
-   define argument strings "rb" and "wb" to be supplied to fopen();
-   unfortunately, most other non-ANSI C versions of fopen do not recognize
-   these as legal.  The "rb" and "wb" forms are used here for ANSI and MS-DOS
-   C compilers only, and the older "r" and "w" forms are used in all other
-   cases.
+   libraries, and those supplied with non-ANSI C compilers under MS-DOS, define
+   argument strings "rb" and "wb" to be supplied to fopen(); unfortunately,
+   most other non-ANSI C versions of fopen do not recognize these as legal.
+   The "rb" and "wb" forms are used here for ANSI and MS-DOS C compilers only,
+   and the older "r" and "w" forms are used in all other cases.
 
 4. Before the ANSI/ISO C standard was adopted, there were at least two
    (commonly used but incompatible) ways of declaring functions with variable
@@ -464,9 +431,10 @@
     return (0);
 }	
 
+
 /* wfdb_getiwfdb reads a new value for WFDB from the file named by the second
-through last characters of the current value.  It maintains a use counter to
-detect looping behavior;  getwfdb() resets the counter to zero.
+through last characters of its input argument.  If that value begins with '@',
+this procedure is repeated, with nesting up to ten levels.
 
 Note that the input file must be local (it is accessed using the standard C I/O
 functions rather than their wfdb_* counterparts).  This limitation is
@@ -477,33 +445,68 @@
 #define SEEK_END 2
 #endif
 
-void wfdb_getiwfdb()
+char *wfdb_getiwfdb(p)
+char *p;
 {
     FILE *wfdbpfile;
+    int i = 0;
+    long len;
 
-    if (getiwfdb_count++ > 10) {
+    for (i = 0; i < 10 && *p == '@'; i++) {
+	if ((wfdbpfile = fopen(p+1, RB)) == NULL) p = "";
+	else {
+	    if (fseek(wfdbpfile, 0L, SEEK_END) == 0)
+		len = ftell(wfdbpfile);
+	    else len = 255;
+	    if ((p = (char *)malloc((unsigned)len+1)) == NULL) p = "";
+	    else {
+		rewind(wfdbpfile);
+		len = fread(p, 1, (int)len, wfdbpfile);
+		while (p[len-1] == '\n' || p[len-1] == '\r')
+		    p[--len] = '\0';
+	    }
+	    (void)fclose(wfdbpfile);
+	}
+    }	
+    if (*p == '@') {
 	wfdb_error("getwfdb: files nested too deeply\n");
-	wfdbpath = "";
+	p = "";
     }
-    else if ((wfdbpfile = fopen(wfdbpath+1, RB)) == NULL)
-	wfdbpath = "";
-    else {
-	long len;
-
-	if (fseek(wfdbpfile, 0L, SEEK_END) == 0)
-	    len = ftell(wfdbpfile);
-	else len = 255;
-	rewind(wfdbpfile);
-	if ((wfdbpath = (char *)malloc((unsigned)len+1)) == NULL)
-	    wfdbpath = "";
-	else {
-	    len = fread(wfdbpath, 1, (int)len, wfdbpfile);
-	    while (wfdbpath[len-1] == '\n' || wfdbpath[len-1] == '\r')
-		wfdbpath[--len] = '\0';
+    return (p);
+}
+
+/* wfdb_export_config is invoked from setwfdb to place the configuration
+   variables into the environment if possible. */
+
+#ifndef HAS_PUTENV
+#define wfdb_export_config()
+#else
+void wfdb_export_config()
+{
+    char *p;
+
+    if (p = (char *)malloc(strlen(wfdbpath)+6)) {
+	sprintf(p, "WFDB=%s", wfdbpath);
+	putenv(p);
+    }
+    if (getenv("WFDBCAL") == NULL) {
+	if (p = malloc(strlen(DEFWFDBCAL)+9)) {
+	    sprintf(p, "WFDBCAL=%s", DEFWFDBCAL);
+	    putenv(p);
 	}
-	(void)fclose(wfdbpfile);
+    }
+    if (getenv("WFDBANNSORT") == NULL) {
+	static char p[14];
+	sprintf(p, "WFDBANNSORT=%d", DEFWFDBANNSORT == 0 ? 0 : 1);
+	putenv(p);
+    }
+    if (getenv("WFDBGVMODE") == NULL) {
+	static char p[13];
+	sprintf(p, "WFDBGVMODE=%d", DEFWFDBGVMODE == 0 ? 0 : 1);
+	putenv(p);
     }
 }
+#endif
 
 /* wfdb_addtopath appends the path component of its string argument (i.e.
 everything except the file name itself) to the end of the WFDB path, provided
@@ -523,7 +526,6 @@
 {
     char *d, *p, *t;
     int i, j, l;
-    static char *nwfdbp;
     struct wfdb_path_component *c0;
 
     if (s == NULL || *s == '\0') return;
@@ -558,14 +560,11 @@
 	return;			/* WFDB path is unchanged */
     }
     (void)strcpy(t, wfdbpath);
-    t[l] = PSEP;		/* append a path separator */
-    for (j = 0; j < i; j++)
-	t[l+j+1] = s[j];	/* append the new path component */
+    t[l++] = PSEP;		/* append a path separator */
+    (void)strncpy(t+l, s, i); 	/* append the new path component */
     t[l+i+1] = '\0';
-    if (wfdbpath == nwfdbp)	/* WFDB path was previously modified by this
-				   function */
-	(void)free(nwfdbp);
-    setwfdb(nwfdbp = t);
+    setwfdb(t);
+    free(t);
 }
 
 /* The wfdb_error function handles error messages, normally by printing them
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/NEWS wfdb-10.3.9/NEWS
--- wfdb-10.3.8/NEWS	2003-07-12 02:39:56.000000000 -0400
+++ wfdb-10.3.9/NEWS	2003-07-16 22:30:19.000000000 -0400
@@ -1,3 +1,18 @@
+10.3.9:
+	The WFDB library functions setwfdb, setannstr, setanndesc, and
+	setecgstr now copy their input string arguments, so that it is
+	no longer necessary for WFDB applications to keep these strings
+	valid.  If you have created applications that rely on being able
+	to modify these strings, it will be necessary to invoke the
+	corresponding functions again before such changes will take effect
+	within the WFDB library.
+
+	Previous versions of the WFDB library function putinfo did not
+	flush their output until either a new header file was created (via
+	setheader or newheader) or the process exited.  This has now been
+	corrected, and putinfo output is now flushed before putinfo returns.
+	Thanks to Jonas Carlson for reporting this problem.
+
 10.3.8:
 	The WFDB library function setbasetime (in lib/signal.c) now properly
 	accepts arguments specifying midnight (e.g., "0:0:0"), which previous
diff -Naur --exclude Makefile --exclude info wfdb-10.3.8/wview/wview.c wfdb-10.3.9/wview/wview.c
--- wfdb-10.3.8/wview/wview.c	2000-06-11 00:11:29.000000000 -0400
+++ wfdb-10.3.9/wview/wview.c	2003-07-16 11:10:39.000000000 -0400
@@ -1,5 +1,5 @@
 /* file: wview.c        G. Moody        20 January 1993
-                        Last revised:     11 June 2000
+                        Last revised:     11 June 2000 (but see *** below)
    
 -------------------------------------------------------------------------------
 wview: view WFDB-format signals and annotations under MS Windows
@@ -568,8 +568,13 @@
       case WM_INITDIALOG:
 	SetDlgItemText(hDlg, IDD_RECORD, record);
 	SetDlgItemText(hDlg, IDD_ANNOTATOR, annotator);
-	if ((t = getwfdb()) != wfdbpath)
+	if ((t = getwfdb()) != wfdbpath) {
 	    strncpy(wfdbpath, t, sizeof(wfdbpath)-1);
+	    setwfdb(wfdbpath);	/* *** 16 July 2003 (GBM).  This call is
+				   necessary for WFDB 10.3.9 and later, in
+				   which setwfdb keeps its own copy of the
+				   WFDB path. */
+	}
 	SetDlgItemText(hDlg, IDD_WFDBPATH, wfdbpath);
 	SetDlgItemText(hDlg, IDD_WFDBCAL, cfname);
 	return (TRUE);
