diff --git a/BUILD.NOTES b/BUILD.NOTES
index bc0dd780148ee66689f2e69f65738a790b4f99d1..d52b6be883db252bee7d8442d4bcc9d75c89c32d 100644
--- a/BUILD.NOTES
+++ b/BUILD.NOTES
@@ -151,7 +151,8 @@ Configuration file update procedures:
 Some RPM commands:
   rpm -qa | grep slurm                  (determine what is installed)
   rpm -qpl slurm-1.1.9-1.rpm            (check contents of an rpm)
-  rpm -e slurm-1.1.8-1                  (erase an rpm
+  rpm -e slurm-1.1.8-1                  (erase an rpm)
+  rpm --upgrade slurm-1.1.9-1.rpm       (replace existing rpm with new version)
   rpm -i --ignoresize slurm-1.1.9-1.rpm (install a new rpm)
 For main SLURM plugin installation on BGL service node:
   rpm -i --force --nodeps --ignoresize slurm-1.1.9-1.rpm
diff --git a/META b/META
index 41e3463a9daac527f86d4f9eba7c42ee29f96ea3..b59079a2bb91c9e6df3c9434bcb6e420f4652509 100644
--- a/META
+++ b/META
@@ -3,9 +3,9 @@
   Api_revision:  0
   Major:         1
   Meta:          1
-  Micro:         4
+  Micro:         5
   Minor:         3
   Name:          slurm
   Release:       1
   Release_tags:  dist
-  Version:       1.3.4
+  Version:       1.3.5
diff --git a/NEWS b/NEWS
index bf08c977106b5138c7395efe5a4c0b5b490027ad..bb862d7c5315fc133c2cdda3b6ad121c568862e3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,23 @@
 This file describes changes in recent versions of SLURM. It primarily
 documents those changes that are of interest to users and admins.
 
+* Changes in SLURM 1.3.5
+========================
+ -- Fix processing of auth/munge authtentication key for messages originating 
+    in slurmdbd and sent to slurmctld. 
+ -- If srun is allocating resources (not within sbatch or salloc) and MaxWait
+    is configured to a non-zero value then wait indefinitely for the resource
+    allocation rather than aborting the request after MaxWait time.
+ -- For Moab only: add logic to reap defunct "su" processes that are spawned by
+    slurmd to load user's environment variables.
+ -- Added more support for "dumping" account information to a flat file and 
+    read in again to protect data incase something bad happens to the database.
+ -- Sacct will now report account names for job steps.
+ -- For AIX: Remove MP_POERESTART_ENV environment variable, disabling poerestart
+    command. User must explicitly set MP_POERESTART_ENV before executing poerestart.
+ -- Put back notification that a job has been allocated resources when it was
+    pending.
+
 * Changes in SLURM 1.3.4
 ========================
  -- Some updates to man page formatting from Gennaro Oliva, ICAR.
@@ -359,6 +376,18 @@ documents those changes that are of interest to users and admins.
 * Changes in SLURM 1.2.32
 =========================
  -- Disable scancel of job in RootOnly partition only for sched/wiki2 (Moab).
+    Permit user scancel from other configurations (e.g. LSF).
+ -- Add support for sbatch --distribution and --network options.
+ -- Correct pending job's wait reason to "Priority" rather than "Resources" if
+    required resources are being held in reserve for a higher priority job.
+ -- In sched/wiki2 (Moab) report a node's state as "Drained" rather than "Draining"
+    if it has no allocated work (An undocumented Moab wiki option, see CRI
+    ticket #2394).
+ -- Log to job's output when it is cancelled or reaches it's time limit (ported
+    from existing code in slurm v1.3).
+ -- Add support in salloc and sbatch commands for --network option.
+ -- Add support for user environment variables that include '\n' (e.g. 
+    bash functions).
 
 * Changes in SLURM 1.2.31
 =========================
@@ -3299,4 +3328,4 @@ documents those changes that are of interest to users and admins.
  -- Change directory to /tmp in slurmd if daemonizing.
  -- Logfiles are reopened on reconfigure.
  
-$Id: NEWS 14322 2008-06-23 22:01:33Z da $
+$Id: NEWS 14453 2008-07-08 20:26:18Z da $
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index e07726a06075fc88acc3c0833bb575d3201a4c9a..3292ec95ac4c6bfe7899d7e6c8c0f95644d04b59 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,5 +1,5 @@
 RELEASE NOTES FOR SLURM VERSION 1.3
-14 May 2008
+27 June 2008
 
 
 IMPORTANT NOTE:
@@ -29,19 +29,27 @@ now supports gang scheduling (time-slicing of parallel jobs for
 improved responsiveness and system utilization). Many related 
 scheduling changes have also been made. 
 
-There are changes in SLURM's RPMs. There is a new RPM called 
-slurmdbd (SLURM DataBase Daemon) used to provide a secure 
-SLURM database interface for accounting purposes (more information 
-about that below). The SLURM plugins have been moved to a new
-RPM called slurm-plugins. If the slurmdbd is installed it 
-requires the slurm-plugins, but not the other slurm components.
-The base SLURM plugin requires the plugins, which used to be
-within that RPM. 
+There are changes in SLURM's RPMs. "slurm-auth-munge" was changed to 
+"slurm-munge" since it now contains the authentication and cryptographic 
+signature plugins for Munge. The SLURM plugins have been moved out of 
+the main "slurm" RPM to a new RPM called "slurm-plugins". There is a 
+new RPM called "slurm-slurmdbd" (SLURM DataBase Daemon). Slurmdbd is 
+used to provide a secure SLURM database interface for accounting purposes 
+(more information about that below). The "slurm-slurmdbd" RPM requires 
+the "slurm-plugins" RPM, but none of the other SLURM RPMs. The main 
+"slurm" RPM also requires the "slurm-plugins" RPM.
+
+To archive accounting records in a database then database RPMs must be 
+installed where the SLURM RPMs are build and where the database is used. 
+You have a choise of database, either "mysql" plus "mysql-devel" or 
+"postgres" plus "postgres-devel" RPMs.
 
 Many enhancements have been made for better Slurm integration with 
-Moab and Maui schedulers. Moab development work is still underway 
-to support Slurm v1.3. Moab users should not upgrade to Slurm v1.3
-until this work has been completed.
+Moab and Maui schedulers. Moab version 5.2.3 or higher should be 
+used with SLURM version 1.3. In the Moab configuration file, moab.cfg,
+change the SUBMITCMD option from "srun --batch" to "sbatch" since the 
+"srun --batch" option is no longer valid (use of full pathnames to 
+the commands are recommended, e.g. "/usr/local/bin/sbatch").
 
 Major changes in Slurm version 1.3 are described below. Some changes
 made after the initial release of Slurm version 1.2 are also noted.
@@ -209,6 +217,12 @@ OTHER CONFIGURATION CHANGES
   added in slurm v1.2.13). Users can override this using the --open-mode
   option when submitting a job.
 
+* A new parameter, EnforcePartLimits, was dded. If set then immediately 
+  reject a job that exceeds a partition's size and/or time limits rather
+  then queued for a later change in the partition's limits. NOTE: Not 
+  reported by "scontrol show config" to avoid changing RPCs. It will be 
+  reported in SLURM version 1.4.
+
 * Checkpoint plugins have been added for XLCH and OpenMPI.
 
 * A new parameter, PrivateData, can be used to prevent users from being 
diff --git a/auxdir/x_ac_databases.m4 b/auxdir/x_ac_databases.m4
index 8bed9a7039708d3745bf5262ea3dcb484b166ea3..776239b8e75fafb206ff332c46a34e8883bc3cd5 100644
--- a/auxdir/x_ac_databases.m4
+++ b/auxdir/x_ac_databases.m4
@@ -48,9 +48,6 @@ AC_DEFUN([X_AC_DATABASES],
 		# want that so we remove it.
 			MYSQL_CFLAGS=`$HAVEMYSQLCONFIG --cflags`
 			MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs_r`
-			if test -z "$MYSQL_LIBS"; then
-				MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs`
-			fi
 			save_CFLAGS="$CFLAGS"
 			save_LIBS="$LIBS"
        			CFLAGS="$MYSQL_CFLAGS $save_CFLAGS"
@@ -73,10 +70,36 @@ AC_DEFUN([X_AC_DATABASES],
 				AC_SUBST(MYSQL_CFLAGS)
 				AC_DEFINE(HAVE_MYSQL, 1, [Define to 1 if using MySQL libaries])
 			else
- 				MYSQL_CFLAGS=""
-				MYSQL_LIBS=""
-       				AC_MSG_WARN([*** MySQL test program execution failed.])
-			fi        	
+				MYSQL_CFLAGS=`$HAVEMYSQLCONFIG --cflags`
+				MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs`
+				save_CFLAGS="$CFLAGS"
+				save_LIBS="$LIBS"
+       				CFLAGS="$MYSQL_CFLAGS $save_CFLAGS"
+				LIBS="$MYSQL_LIBS $save_LIBS"
+				AC_TRY_LINK([#include <mysql.h>],[
+          					int main()
+          					{
+							MYSQL mysql;
+            						(void) mysql_init(&mysql);
+							(void) mysql_close(&mysql);
+            					}
+        					],
+					[ac_have_mysql="yes"],
+					[ac_have_mysql="no"])
+				CFLAGS="$save_CFLAGS"
+				LIBS="$save_LIBS"
+				
+    				if test "$ac_have_mysql" == "yes"; then
+            				AC_MSG_RESULT([MySQL (non-threaded) test program built properly.])
+            				AC_SUBST(MYSQL_LIBS)
+					AC_SUBST(MYSQL_CFLAGS)
+					AC_DEFINE(HAVE_MYSQL, 1, [Define to 1 if using MySQL libaries])
+				else
+					MYSQL_CFLAGS=""
+					MYSQL_LIBS=""
+          				AC_MSG_WARN([*** MySQL test program execution failed.])
+				fi        	
+			fi
 		fi
       	fi
 
diff --git a/configure b/configure
index 4da1885653546ef99a7b915c1f0d871deeff3a47..fe472cf3a0e361b3137bba160dbf42f97c83dd9a 100755
--- a/configure
+++ b/configure
@@ -25500,9 +25500,6 @@ echo "$as_me: WARNING: *** mysql-$mysql_config_major_version.$mysql_config_minor
 		# want that so we remove it.
 			MYSQL_CFLAGS=`$HAVEMYSQLCONFIG --cflags`
 			MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs_r`
-			if test -z "$MYSQL_LIBS"; then
-				MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs`
-			fi
 			save_CFLAGS="$CFLAGS"
 			save_LIBS="$LIBS"
        			CFLAGS="$MYSQL_CFLAGS $save_CFLAGS"
@@ -25570,10 +25567,81 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
 			else
- 				MYSQL_CFLAGS=""
-				MYSQL_LIBS=""
-       				{ echo "$as_me:$LINENO: WARNING: *** MySQL test program execution failed." >&5
+				MYSQL_CFLAGS=`$HAVEMYSQLCONFIG --cflags`
+				MYSQL_LIBS=`$HAVEMYSQLCONFIG --libs`
+				save_CFLAGS="$CFLAGS"
+				save_LIBS="$LIBS"
+       				CFLAGS="$MYSQL_CFLAGS $save_CFLAGS"
+				LIBS="$MYSQL_LIBS $save_LIBS"
+				cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <mysql.h>
+int
+main ()
+{
+
+          					int main()
+          					{
+							MYSQL mysql;
+            						(void) mysql_init(&mysql);
+							(void) mysql_close(&mysql);
+            					}
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_have_mysql="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_have_mysql="no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+				CFLAGS="$save_CFLAGS"
+				LIBS="$save_LIBS"
+
+    				if test "$ac_have_mysql" == "yes"; then
+            				{ echo "$as_me:$LINENO: result: MySQL (non-threaded) test program built properly." >&5
+echo "${ECHO_T}MySQL (non-threaded) test program built properly." >&6; }
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MYSQL 1
+_ACEOF
+
+				else
+					MYSQL_CFLAGS=""
+					MYSQL_LIBS=""
+          				{ echo "$as_me:$LINENO: WARNING: *** MySQL test program execution failed." >&5
 echo "$as_me: WARNING: *** MySQL test program execution failed." >&2;}
+				fi
 			fi
 		fi
       	fi
diff --git a/contribs/Makefile.am b/contribs/Makefile.am
index 77afcd59aac66e5b969cbc10a28d387b048fb3cd..74bb21836d363f13b6174c3299c5f069d29741de 100644
--- a/contribs/Makefile.am
+++ b/contribs/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = perlapi phpext torque 
+SUBDIRS = perlapi torque 
 
 EXTRA_DIST = \
 	env_cache_builder.c	\
diff --git a/contribs/Makefile.in b/contribs/Makefile.in
index dffadf88374f2f6a320014b061c945b450afe30f..4040f4ef3d983977e84987880c21236773e99b59 100644
--- a/contribs/Makefile.in
+++ b/contribs/Makefile.in
@@ -245,7 +245,7 @@ target_os = @target_os@
 target_vendor = @target_vendor@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-SUBDIRS = perlapi phpext torque 
+SUBDIRS = perlapi torque 
 EXTRA_DIST = \
 	env_cache_builder.c	\
 	make.slurm.patch	\
diff --git a/doc/html/accounting.shtml b/doc/html/accounting.shtml
index af84b48ddf47800843851256a23686314d069452..6a2138ab877df2e5c61eeaccd9546c61976f68af 100644
--- a/doc/html/accounting.shtml
+++ b/doc/html/accounting.shtml
@@ -1,21 +1,27 @@
 <!--#include virtual="header.txt"-->
 
 <h1>Accounting</h1>
-<p>SLURM collects accounting information for every job and job step 
-executed. 
+
+<p>NOTE: This documents accounting features available in SLURM version 
+1.3, which are far more extensive than those available in previous 
+releases.</p>
+
+<p>SLURM can be configured to collect accounting information for every 
+job and job step executed. 
+Accounting records can be written to a simple file or a database.
 Information is available about both currently executing jobs and 
 jobs which have already terminated and can be viewed using the 
-<b>sacct</b> command. 
-Resource usage is reported for each task and this can be useful to 
-detect load imbalance between the tasks. 
-SLURM version 1.2 and earlier supported the storage of accounting 
-records to a text file.
-Beginning in SLURM version 1.3 accounting records can be written to 
-a database. </p>
+<b>sacct</b> command.
+<b>sacct</b> can also report resource usage for individual tasks, 
+which can be useful to detect load imbalance between the tasks. 
+The <b>sstat</b> tool can be used to status a currently running job.
+The <b>sreport</b> can be used to generate reports based upon all jobs
+executed in a particular time interval.</p>
 
 <p>There are three distinct plugin types associated with resource accounting.
-The configuration parameters associated with these plugins include:
-</p><ul>
+The SLURM configuration parameters (in <i>slurm.conf</i>) associated with 
+these plugins include:</p>
+<ul>
 <li><b>JobCompType</b> controls how job completion information is 
 recorded. This can be used to record basic job information such
 as job name, user name, allocated nodes, start time, completion 
@@ -24,9 +30,7 @@ information is required, this plugin should satisfy your needs
 with minimal overhead. You can store this information in a 
 text file, <a href="http://www.mysql.com/">MySQL</a> or 
 <a href="http://www.postgresql.org/">PostgreSQL</a> 
-database optionally using either 
-<a href="http://www.clusterresources.com/pages/products/gold-allocation-manager.php">Gold</a>
-or SlurmDBD for added database security.</li>
+database</li>
 <li><b>JobAcctGatherType</b> is operating system dependent and 
 controls what mechanisms are used to collect accounting information.
 Supported values are <i>jobacct_gather/aix</i>, <i>jobacct_gather/linux</i>
@@ -40,8 +44,14 @@ database optionally using either
 or SlurmDBD for added security.</li>
 </ul>
 
-<p>Storing the information into text files is very simple. 
-Just configure the appropriate plugin (e.g. 
+<p>The use of sacct or sstat to view information about completed jobs 
+is dependent upon both JobAcctGatherType and JobAcctGatherType
+being configured to collect and store that information.
+The use of sreport is dependent upon some database being 
+used to store that information.</p>
+
+<p>Storing the accounting information into text files is 
+very simple. Just configure the appropriate plugin (e.g. 
 <i>AccountingStorageType=accounting_storage/filetxt</i> and/or 
 <i>JobCompType=jobcomp/filetxt</i>) and then specify the 
 pathname of the file (e.g.
@@ -54,13 +64,14 @@ after moving the files, but before compressing them so
 that new log files will be created.</p>
 
 <p>Storing the data directly into a database from SLURM may seem 
-attractive, but that requires the availability of user name and 
+attractive, but requires the availability of user name and 
 password data not only for the SLURM control daemon (slurmctld), 
-but also user commands which need to access the data (sacct and
+but also user commands which need to access the data (sacct, sreport, and
 sacctmgr). 
-Making information available to all users makes database security 
-more difficult to provide, sending the data through an intermediate
-daemon can provide better security. 
+Making possibly sensitive information available to all users makes 
+database security more difficult to provide, sending the data through
+an intermediate daemon can provide better security and performance
+(through caching data).
 Gold and SlurmDBD are two such services. 
 Our initial implementation relied upon Gold, but we found its
 performance to be inadequate for our needs and developed SlurmDBD.
@@ -78,40 +89,101 @@ is to execute.</p>
 
 <h2>Infrastructure</h2>
 
-<p>If the SlurmDBD is executed on a different cluster than the 
-one managed by SLURM, possibly to collect data from multiple 
-clusters in a single location, there are some constraints on 
-the user space.
-The user ID associated with <i>SlurmUser</i> must be uniform 
-across all clusters. 
+<p>With the SlurmDBD, we are able to collect data from multiple 
+clusters in a single location.
+This does impose some constraints on the user naming and IDs.
 Accounting is maintained by user name (not user ID), but a
 given user name should refer to the same person across all 
-of the computers.</p>
+of the computers. 
+Authentication relies upon user ID numbers, so those must 
+be uniform across all computers communicating with each
+SlurmDBD, at least for users requiring authentication.
+In particular, the configured <i>SlurmUser</i> must have the
+same name and ID across all clusters.
+If you plan to have administrators of user accounts, limits, 
+etc. they must also have consistent names and IDs across all 
+clusters.
+If you plan to restrict access to accounting records (e.g. 
+only permit a user to view records of his jobs), then all 
+users should have consistent names and IDs.</p>
 
 <p>The best way to insure security of the data is by authenticating 
 communications to the SlurmDBD and we recommend 
 <a href="http://home.gna.org/munge/">Munge</a> for that purpose.
-Munge was designed to support authentication within a cluster.
 If you have one cluster managed by SLURM and execute the SlurmDBD 
 on that one cluster, the normal Munge configuration will suffice.
 Otherwise Munge should then be installed on all nodes of all 
-SLURM managed clusters plus the machine where SlurmDBD executes.
+SLURM managed clusters, plus the machine where SlurmDBD executes.
 You then have a choice of either having a single Munge key for 
 all of these computers or maintaining a unique key for each of the 
 clusters plus a second key for communications between the clusters
 for better security.
 Munge enhancements are planned to support two keys within a single 
 configuration file, but presently two different daemons must be 
-started with different configuration files to support two different 
-keys. 
-If a Munge separate daemon configured to provide enterprise-wide 
-authentication, it will have a unique named pipe configured for 
-communications. 
-The pathname of this pipe will be needed in the SLURM and SlurmDBD
-configuration files (slurm.conf and slurmdbd.conf respectively, 
-more details are provided below).</p>
+started with different configurations to support two different keys 
+(create two key files and start the daemons with the 
+<i>--key-file</i> option to locate the proper key plus the
+<i>--socket</i> option to specify distinct local domain sockets for each).
+The pathname of local domain socket will be needed in the SLURM 
+and SlurmDBD configuration files (slurm.conf and slurmdbd.conf 
+respectively, more details are provided below).</p>
+
+<h2>Slurm JobComp Configuration</h2>
+
+<p>Presently job completion is not supported with the SlurmDBD, but can be
+written directly to a database, script or flat file.If you are
+running with the accounting storage, you may not need to run this
+since it contains much of the same information.If you would like
+to configure this, some of the more important parameters include:</p>
 
-<h2>SLURM Configuration</h2>
+<ul>
+<li><b>JobCompHost</b>:
+Only needed if using a database. The name or address of the host where
+the database server executes.</li>
+
+<li><b>JobCompPass</b>:
+Only needed if using a database. Password for the user connecting to
+the database.</li>
+
+<li><b>JobCompPort</b>:
+Only needed if using a database. The network port that the database
+accepts communication on.</li>
+
+<li><b>JobCompType</b>:
+Type of jobcomp plugin set to "jobcomp/mysql", "jobcomp/pgsql", or
+"jobcomp/filetxt".</li>
+
+<li><b>JobCompUser</b>:
+Only needed if using a database. User name to connect to
+the database with.</li>
+</ul>
+
+<h2>SLURM Accounting Configuration Before Build</h2>
+
+<p>While the SlurmDBD will work with a flat text file for recording
+job completions and such this configuration will not allow
+"associations" between a user and account. A database allows such
+a configuration. MySQL is the preferred database, PostgreSQL is
+supported for job and step accounting only. The infrastructure for
+associations is not yet supported. To enable this database support
+one only needs to have the development package for the database they
+wish to use on the system. The slurm configure script uses
+mysql_config and pg-config to find out the information it needs
+about installed libraries and headers. You can specify where your
+mysql_config script is with the
+</i>--with-mysql_conf=/path/to/mysql_config</i> option when configuring your
+slurm build. A similar option is available for PostgreSQL also. On
+a successful configure, output is something like this: </p>
+<pre>
+checking for mysql_config... /usr/bin/mysql_config
+MySQL test program built properly.
+</pre>
+
+<h2>SLURM Accounting Configuration After Build</h2>
+
+<p>For simplicity sake we are going to reference everything as if you
+are running with the SlurmDBD. You can communicate with a storage plugin
+directly, but that offers minimal authentication. 
 
 <p>Several SLURM configuration parameters must be set to support
 archiving information in SlurmDBD. SlurmDBD has a separate configuration
@@ -125,18 +197,19 @@ with "JobComp" then job completion records will not be recorded.</p>
 <ul>
 <li><b>AccountingStorageEnforce</b>:
 If you want to prevent users from running jobs if their <i>association</i>
-(a combination of cluster, account, and user names. For more
-flexibility in accounting the association can also include a partition
-name, but it is not necissary.) is not in the database, then set this
-to "1". Otherwise jobs will be executed based upon policies configured
-in SLURM on each cluster. </li>
+is not in the database, then set this to "1". 
+(NOTE: The association is a combination of cluster, account, 
+user names and optional partition name.)
+Without AccountingStorageEnforce being set (the default behavior) 
+jobs will be executed based upon policies configured in SLURM on each cluster. 
+This option will prevent users from accessing invalid accounts.</li>
 
-<li><b>AccountingStorageHost</b>: The name or address of the host where SlurmDBD executes
-      </li>
+<li><b>AccountingStorageHost</b>: The name or address of the host where 
+SlurmDBD executes</li>
 
 <li><b>AccountingStoragePass</b>: If using SlurmDBD with a second Munge
 daemon, store the pathname of the named socket used by Munge to provide
-enterprise-wide. Otherwise the default Munge daemon will be used. . </li>
+enterprise-wide. Otherwise the default Munge daemon will be used.</li>
 
 <li><b>AccountingStoragePort</b>:
 The network port that SlurmDBD accepts communication on.</li>
@@ -147,20 +220,6 @@ Set to "accounting_storage/slurmdbd".</li>
 <li><b>ClusterName</b>:
 Set to a unique name for each Slurm-managed cluster so that 
 accounting records from each can be identified.</li>
-
-<li><b>JobCompHost</b>:
-The name or address of the host where SlurmDBD executes.</li>
-
-<li><b>JobCompPass</b>:
-If using SlurmDBD with a second Munge daemon, store the pathname of 
-the named socket used by Munge to provide enterprise-wide.
-Otherwise the default Munge daemon will be used.</li>
-
-<li><b>JobCompPort</b>:
-The network port that SlurmDBD accepts communication on.</li>
-
-<li><b>JobCompType</b>:
-Set to "jobcomp/slurmdbd".</li>
 </ul>
 
 <h2>SlurmDBD Configuration</h2>
@@ -187,7 +246,8 @@ components. A value of "auth/munge" is recommended.</li>
 <li><b>DbdHost</b>:
 The name of the machine where the Slurm Database Daemon is executed. 
 This should be a node name without the full domain name (e.g. "lx0001"). 
-This value must be specified.</li>
+This defaults to <i>localhost</i> but should be supplied to avoid a
+warning message.</li>
 
 <li><b>DbdPort</b>:
 The port number that the Slurm Database Daemon (slurmdbd) listens 
@@ -205,24 +265,26 @@ The default value is none (performs logging via syslog).</li>
 Identifies the places in which to look for SLURM plugins. 
 This is a colon-separated list of directories, like the PATH 
 environment variable. 
-The default value is "/usr/local/lib/slurm".</li>
+The default value is the prefix given at configure time + "/lib/slurm".</li>
 
 <li><b>SlurmUser</b>:
 The name of the user that the <i>slurmctld</i> daemon executes as. 
 This user must exist on the machine executing the Slurm Database Daemon
 and have the same user ID as the hosts on which <i>slurmctld</i> execute.
 For security purposes, a user other than "root" is recommended.
-The default value is "root". </li>
+The default value is "root". This name should also be the same SlurmUser 
+on all clusters reporting to the SlurmDBD.</li>
 
 <li><b>StorageHost</b>:
 Define the name of the host the database is running where we are going
 to store the data.
-Ideally this should be the host on which slurmdbd executes.</li>
+Ideally this should be the host on which SlurmDBD executes. But could
+be a different machine.</li>
 
 <li><b>StorageLoc</b>:
 Specifies the name of the database where accounting 
 records are written, for databases the default database is
-slurm_acct_db.  Note the name can not have a '/' in it or the
+slurm_acct_db. Note the name can not have a '/' in it or the
 default will be used.</li>
 
 <li><b>StoragePass</b>:
@@ -254,28 +316,59 @@ Define the name of the user we are going to connect to the database
 with to store the job accounting data.</li>
 </ul>
 
+<h2>MySQL Configuration</h2>
+
+<p>While SLURM will create the database automatically you will need to
+make sure the StorageUser is given permissions in MySQL to do so.
+As the <i>mysql</i> user grant privileges to that user using a
+command such as 
+
+<pre>
+GRANT ALL ON StorageLoc.* TO 'StorageUser'@'StorageHost';
+(The ticks are needed)
+
+live example:
+
+mysql@snowflake:~$ mysql
+Welcome to the MySQL monitor.Commands end with ; or \g.
+Your MySQL connection id is 538
+Server version: 5.0.51a-3ubuntu5.1 (Ubuntu)
+
+Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
+
+mysql> grant all on slurm_acct_db.* TO 'da'@'localhost';
+Query OK, 0 rows affected (0.00 sec)
+</pre>
+
+<p>This will grant user 'da' access to do what he needs to do on the
+local host. This should be done before the SlurmDBD will work
+properly.</p>
+
 <h2>Tools</h2>
 
-<p>There are two tools available to work with accounting data,
-<b>sacct</b> and <b>sacctmgr</b>. 
-Both of these tools will get or set data through the SlurmDBD daemon. 
-Sacct is used to generate accounting report for both running and 
-completed jobs.
-Sacctmgr is used to manage associations in the database: 
-add or remove clusters, add or remove users, etc.
-See the man pages for each command for more information.</p>
+<p>There are a few tools available to work with accounting data,
+<b>sacct</b>, <b>sacctmgr</b>, and <b>sreport</b>. 
+These tools all get or set data through the SlurmDBD daemon.
+<ul>
+<li><b>sacct</b> is used to generate accounting report for both 
+running and completed jobs.</li>
+<li><b>sacctmgr</b> is used to manage associations in the database: 
+add or remove clusters, add or remove users, etc.</li>
+<li><b>sreport</b> is used to generate various reports on usage collected over a
+given time period.</li>
+</ul>
+<p>See the man pages for each command for more information.</p>
 
 <p>Web interfaces with graphical output is currently under
-development and should be available in the summer of 2008.
+development and should be available in the Fall of 2008.
 A tool to report node state information is also under development.</p>
 
 <h2>Database Configuration</h2>
 
 <p>Accounting records are maintained based upon what we refer 
 to as an <i>Association</i>,
-which consists of four elements: cluster, account, and user names. For
-more flexibility in accounting the association can also include a
-partition name, but it is not necessary. Use the <i>sacctmgr</i>
+which consists of four elements: cluster, account, user names and
+an optional partition name. Use the <i>sacctmgr</i>
 command to create and manage these records. There is an order to set up
 accounting associations. You must define clusters before you add
 accounts and you must add accounts before you can add users. </p>
@@ -293,26 +386,26 @@ sacctmgr add account none,test Cluster=snowflake \
   Description="none" Organization="none" 
 </pre>
 
-<p>If you have more clusters you want to add these accounts to you
+<p>If you have more clusters you want to add these accounts, to you
 can either not specify a cluster, which will add the accounts to all
 clusters in the system, or comma separate the cluster names you want
 to add to in the cluster option.
 Note that multiple accounts can be added at the same time 
 by comma separating the names. 
-Some Description of the account and the organization which it belongs
-must be specified. 
+Some <i>description</i> of the account and the <i>organization</i> which 
+it belongs must be specified. 
 These terms can be used later to generated accounting reports.
 Accounts may be arranged in a hierarchical fashion, for example accounts 
 <i>chemistry</i> and <i>physics</i> may be children of the account <i>science</i>. 
 The hierarchy may have an arbitrary depth. 
-To do this one only needs to specify the <i>parent='' </i>option in the add 
-account line.
+Just specify the <i>parent=''</i> option in the add account line to construct
+the hierarchy.
 For the example above execute</p>
 <pre>
 sacctmgr add account science \
-   Description="science accounts" Organization=science
+ Description="science accounts" Organization=science
 sacctmgr add account chemistry,physics parent=science \
-   Description="physical sciences" Organization=science
+ Description="physical sciences" Organization=science
 </pre>
 
 <p>Add users to accounts using similar syntax.
@@ -321,14 +414,15 @@ with a default account of <i>test</i> execute:</p>
 <pre>
 sacctmgr add user da default=test
 </pre>
+
 <p>If <b>AccountingStorageEnforce=1</b> is configured in the slurm.conf of 
 the cluster <i>snowflake</i> then user <i>da</i> would be
 allowed to run in account <i>test</i> and any other accounts added
 in the future.
 Any attempt to use other accounts will result in the job being 
 aborted. 
-Account <i>test</i> will be the default if he doesn't specify one in a 
-srun line.</p>
+Account <i>test</i> will be the default if he doesn't specify one in 
+the job submission command.</p>
 
 <p>Partition names can also be added to an "add user" command with the
 Partition='partitionname' option to specify an association specific to
@@ -395,7 +489,7 @@ options are available:
 <li><b>Name=</b> User name</li>
 
 <li><b>DefaultAccount=</b> Default account for the user, used when no account 
-is specified when a job is sumbitted. (Required on creation)</li>
+is specified when a job is submitted. (Required on creation)</li>
 
 <li><b>AdminLevel=</b> This field is used to allow a user to add accounting 
 privileges to this user. Valid options are 
@@ -465,14 +559,11 @@ execute line:</p>
 <pre>
 sacctmgr remove user where default=test
 </pre>
+<p>Note: In most cases, removed entities are preserved, but flagged
+as deleted. 
+If an entity has existed for less than 1 day, the entity will be removed 
+completely. This is meant to clean up after typographic errors.</p>
 
-<h2>Node State Information</h2>
-
-<p>Node state information is also recorded in the database. 
-Whenever a node goes DOWN or becomes DRAINED that event is 
-logged along with the node's <i>Reason</i> field. 
-This can be used to generate various reports.
-
-<p style="text-align: center;">Last modified 25 March 2008</p>
+<p style="text-align: center;">Last modified 27 June 2008</p>
 
 </ul></body></html>
diff --git a/doc/html/download.shtml b/doc/html/download.shtml
index 8c7208c189b627eb04f2ba20d244810534c2ba27..5b78cbbab7ad8136a01fadb0744cbfa81721b67b 100644
--- a/doc/html/download.shtml
+++ b/doc/html/download.shtml
@@ -2,12 +2,13 @@
 
 <h1>Download</h1>
 <p>
-SLURM source can be downloaded from <br>
-<a href="https://sourceforge.net/projects/slurm/">
-https://sourceforge.net/projects/slurm/</a><br>
-There is also a Debian package named <i>slurm-llnl</i> available at <br>
-<a href="http://www.debian.org/">http://www.debian.org/</a><br>
-The latest stable release of SLURM is version 1.3.</p>
+SLURM source can be downloaded from 
+<a href="http://sourceforge.net/projects/slurm/">
+http://sourceforge.net/projects/slurm/</a><br>
+SLURM has also been packaged for 
+<a href="http://packages.debian.org/src:slurm-llnl">Debian</a> and 
+<a href="http://packages.ubuntu.com/src:slurm-llnl">Ubuntu</a>
+(both named <i>slurm-llnl</i>).</p>
 
 <p> Other software available for download includes
 <ul>
@@ -100,6 +101,6 @@ Portable Linux Processor Affinity (PLPA)</a></li>
 
 </ul>
 
-<p style="text-align:center;">Last modified 28 March 2008</p>
+<p style="text-align:center;">Last modified 27 June 2008</p>
 
 <!--#include virtual="footer.txt"-->
diff --git a/doc/html/faq.shtml b/doc/html/faq.shtml
index ac6d62e6f42edef04d00c0d1df8eec6fb4958651..0f6d6baac6081046e41a4e68edd89dd041992798 100644
--- a/doc/html/faq.shtml
+++ b/doc/html/faq.shtml
@@ -89,7 +89,7 @@ regular database plugins?</li>
 When a job is terminating, both the job and its nodes enter the COMPLETING state. 
 As the SLURM daemon on each node determines that all processes associated with 
 the job have terminated, that node changes state to IDLE or some other appropriate 
-state. 
+state for use by other jobs. 
 When every node allocated to a job has determined that all processes associated 
 with it have terminated, the job changes state to COMPLETED or some other 
 appropriate state (e.g. FAILED). 
@@ -109,6 +109,13 @@ Note that setting the node DOWN will terminate all running or suspended
 jobs associated with that node. 
 An alternative is to set the node's state to DRAIN until all jobs 
 associated with it terminate before setting it DOWN and re-booting.</p>
+<p>Note that SLURM has two configuration parameters that may be used to 
+automate some of this process.
+<i>UnkillableStepProgram</i> specifies a program to execute when 
+non-killable proceses are identified.
+<i>UnkillableStepTimeout</i> specifies how long to wait for processes
+to terminate. 
+See the "man slurm.conf" for more information about these parameters.</p>
 
 <p><a name="rlimit"><b>2. Why are my resource limits not propagated?</b></a><br>
 When the <span class="commandline">srun</span> command executes, it captures the 
@@ -947,6 +954,6 @@ slurmdbd.
 
 <p class="footer"><a href="#top">top</a></p>
 
-<p style="text-align:center;">Last modified 13 May 2008</p>
+<p style="text-align:center;">Last modified 1 July 2008</p>
 
 <!--#include virtual="footer.txt"-->
diff --git a/doc/html/sched_policy.shtml b/doc/html/sched_policy.shtml
new file mode 100644
index 0000000000000000000000000000000000000000..b7a23b530b76aa783cf710b6edf65424b48216d2
--- /dev/null
+++ b/doc/html/sched_policy.shtml
@@ -0,0 +1,109 @@
+<!--#include virtual="header.txt"-->
+
+<h1>Sheduling Policy</h1>
+
+<p>SLURM scheduling policy support was significantly changed
+in version 1.3 in order to take advantage of the database 
+integration used for storing accounting information.
+This document describes the capabilities available in 
+SLURM version 1.3.4.
+New features are under active development. 
+Familiarity with SLURM's <a href="accounting">Accounting</a> web page
+is strongly recommended before use of this document.</p>
+
+<h2>Configuration</h2>
+
+<p>Scheduling policy information must be stored in a database 
+as specified by the <b>AccountingStorageType</b> configuration parameter
+in the <b>slurm.conf</b> configuration file.
+Information can be recorded in either <a href="http://www.mysql.com/">MySQL</a> 
+or <a href="http://www.postgresql.org/">PostgreSQL</a>.
+For security and performance reasons, the use of 
+SlurmDBD (SLURM Database Daemon) as a front-end to the 
+database is strongly recommended. 
+SlurmDBD uses a SLURM authentication plugin (e.g. Munge).
+SlurmDBD also uses an existing SLURM accounting storage plugin
+to maximize code reuse.
+SlurmDBD uses data caching and prioritization of pending requests
+in order to optimize performance.
+While SlurmDBD relies upon existing SLURM plugins for authentication 
+and database use, the other SLURM commands and daemons are not required 
+on the host where SlurmDBD is installed. 
+Only the <i>slurmdbd</i> and <i>slurm-plugins</i> RPMs are required
+for SlurmDBD execution.</p>
+
+<p>Both accounting and scheduling policy are configured based upon
+an <i>association</i>. An <i>association</i> is a 4-tuple consisting 
+of the cluster name, bank account, user and (optionally) the SLURM 
+partition.
+In order to enforce scheduling policy, set the value of 
+<b>AccountingStorageEnforce</b> to "1" in <b>slurm.conf</b>.
+This prevents users from running any jobs without an valid
+<i>association</i> record in the database and enforces scheduling 
+policy limits that have been configured.</p>
+
+<h2>Tools</h2>
+
+<p>The tool used to manage accounting policy is <i>sacctmgr</i>.
+It can be used to create and delete cluster, user, bank account, 
+and partition records plus their combined <i>association</i> record.
+See <i>man sacctmgr</i> for details on this tools and examples of 
+its use.</p>
+
+<p>A web interface with graphical output is currently under development.</p>
+
+<p>Changes made to the scheduling policy are uploaded to 
+the SLURM control daemons on the various clusters and take effect 
+immediately. When an association is delete, all jobs running or 
+pending which belong to that association are immediately cancelled.
+When limits are lowered, running jobs will not be cancelled to 
+satisfy the new limits, but the new lower limits will be enforced.</p>
+
+<h2>Policies supported</h2>
+
+<p> A limited subset of scheduling policy options are currently 
+supported. 
+The available options are expected to increase as development 
+continues. 
+Most of these scheduling policy options are available not only 
+for an association, but also for each cluster and account. 
+If a new association is created for some user and some scheduling 
+policy options is not specified, the default will be the option 
+for the cluster plus account pair and if that is not specified 
+then the cluster and if that is not specified then no limit 
+will apply.</p>
+
+<p>Currently available cheduling policy options:</p>
+<ul>
+<li><b>MaxJobs</b> Maxiumum number of running jobs for this association</li>
+<li><b>MaxNodes</b> Maxiumum number of nodes for any single jobs in this association</li>
+<li><b>MaxWall</b> Maxiumum wall clock time limit for any single jobs in this association</li>
+</ul>
+
+<p>The <b>MaxNodes</b> and <b>MaxWall</b> options already exist in 
+SLURM's configuration on a per-partition basis, but these options 
+provide the ability to establish limits on a per-user basis.
+The <b>MaxJobs</b> option provides an entirely new mechanism 
+for SLURM to control the workload any individual may place on
+a cluster in order to achieve some balance between users.</p>
+
+<p>The next scheduling policy expected to be added is the concept 
+of fair-share scheduling based upon the hierarchical bank account
+data is already maintained in the SLURM database. 
+The priorities of pending jobs will be adjusted in order to 
+deliver resources in proportion to each association's fair-share.
+Consider the trivial example of a single bank account with 
+two users named Alice and Brian. 
+We might allocate Alice 60 percent of the resources and Brian the 
+remaining 40 precent.
+If Alice has actually used 80 percent of available resources in the 
+recent past, then Brian's pending jobs will automatically be given a
+higher priority than Alice's in order to deliver resources in 
+proportion to the fair-share target. 
+The time window considered in fair-share scheduling will be configurable 
+as well as the relative importance of job age (time waiting to run), 
+but this this example illustrates the concepts involved.</p>
+
+<p style="text-align: center;">Last modified 24 June 2008</p>
+
+</ul></body></html>
diff --git a/doc/man/man1/sacctmgr.1 b/doc/man/man1/sacctmgr.1
index d6874d63a78ffaeeb0861e565c9ab5e5f21510e3..5c29d74d5bf5e0989da6611e733b4b7a47bfad6c 100644
--- a/doc/man/man1/sacctmgr.1
+++ b/doc/man/man1/sacctmgr.1
@@ -40,11 +40,23 @@ This is equivalent to the \fBhelp\fR command.
 Do not display information about hidden or deleted entities. 
 This is equivalent to the \fBhide\fR command.
 
+.TP
+\fB\-\-immediate\fR
+commit changes immediately.
+
+.TP
+\fB\-n\fR, \fB\-\-no_header\fR
+Don't display header when listing results.
+
 .TP
 \fB\-o\fR, \fB\-\-oneliner\fR
 Print information one line per record.
 This is equivalent to the \fBoneliner\fR command.
 
+.TP
+\fB\-n\fR, \fB\-\-parsable\fR
+Make output '|' delimited.
+
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
 Print no warning or informational messages, only error messages.
@@ -65,8 +77,7 @@ This is equivalent to the \fBverbose\fR command.
 Print version information and exit.
 This is equivalent to the \fBversion\fR command.
 
-.TP
-\fBCOMMANDS\fR
+.SH "COMMANDS"
 
 .TP
 \fBall\fR
@@ -331,9 +342,11 @@ To clear a previously set value use the modify command with a new value of \-1.
 .br
 > sacctmgr create account name=chemistry parent=science fairshare=30
 .br
-> sacctmgr create account name=physics   parent=science fairshare=20
+> sacctmgr create account name=physics parent=science fairshare=20
 .br
-> sacctmgr create user name=adam cluster=tux account=physics fairshare=10
+> sacctmgr create user name=adam cluster=tux account=physics \
+.br 
+  fairshare=10
 .br
 > sacctmgr modify user with name=adam cluster=tux account=physics \
 .br
diff --git a/doc/man/man1/salloc.1 b/doc/man/man1/salloc.1
index b1be91d9f6e2c539ac14fc09d78d0e5eb27c54e6..72a8bcdb59faa95ac8eb3d090dc780317ff03b39 100644
--- a/doc/man/man1/salloc.1
+++ b/doc/man/man1/salloc.1
@@ -360,6 +360,22 @@ The default is one task per socket or core (depending upon the value
 of the \fISelectTypeParameters\fR parameter in slurm.conf), but note 
 that the \fB\-\-cpus\-per\-task\fR option will change this default.
 
+.TP
+\fB\-\-network\fR=\fItype\fR
+Specify the communication protocol to be used. 
+This option is supported on AIX systems.
+Since POE is used to launch tasks, this option is not normally used or 
+is specified using the \fBSLURM_NETWORK\fR environment variable.
+The interpretation of \fItype\fR is system dependent. 
+For systems with an IBM Federation switch, the following 
+comma\-separated and case insensitive types are recongnized:
+\fBIP\fR (the default is user\-space), \fBSN_ALL\fR, \fBSN_SINGLE\fR, 
+\fBBULK_XFER\fR and adapter names  (e.g. \fBSNI0\fR and \fBSNI1\fR). 
+For more information, on IBM systems see \fIpoe\fR documenation on 
+the environment variables \fBMP_EUIDEVICE\fR and \fBMP_USE_BULK_XFER\fR.
+Note that only four jobs steps may be active at once on a node with the 
+\fBBULK_XFER\fR option due to limitations in the Federation switch driver.
+
 .TP 
 \fB\-\-nice\fR[=]<\fIadjustment\fR>
 Run the job with an adjusted scheduling priority within SLURM.
@@ -606,6 +622,9 @@ Same as \fB\-I\fR or \fB\-\-immediate\fR.
 \fBSALLOC_JOBID\fR
 Same as \fB\-\-jobid\fR.
 .TP
+\fBSALLOC_NETWORK\fR
+Same as \fB\-\-network\fR.
+.TP
 \fBSALLOC_NO_BELL\fR
 Same as \fB\-\-no\-bell\fR.
 .TP
diff --git a/doc/man/man1/sbatch.1 b/doc/man/man1/sbatch.1
index 77b50cfd50f4c6f62c7078dfbcaba50fdfa6f870..03accb92bfec2f88a4b977225ab4a960d1835ae9 100644
--- a/doc/man/man1/sbatch.1
+++ b/doc/man/man1/sbatch.1
@@ -383,6 +383,21 @@ The default is one task per socket or core (depending upon the value
 of the \fISelectTypeParameters\fR parameter in slurm.conf), but note 
 that the \fB\-\-cpus\-per\-task\fR option will change this default.
 
+.TP
+\fB\-\-network\fR=\fItype\fR
+Specify the communication protocol to be used. 
+This option is supported on AIX systems.
+This option sets the \fBSLURM_NETWORK\fR environment variable for use by POE.
+The interpretation of \fItype\fR is system dependent. 
+For systems with an IBM Federation switch, the following 
+comma\-separated and case insensitive types are recongnized:
+\fBIP\fR (the default is user\-space), \fBSN_ALL\fR, \fBSN_SINGLE\fR, 
+\fBBULK_XFER\fR and adapter names  (e.g. \fBSNI0\fR and \fBSNI1\fR). 
+For more information, on IBM systems see \fIPOE\fR documentation on 
+the environment variables \fBMP_EUIDEVICE\fR and \fBMP_USE_BULK_XFER\fR.
+Note that only four jobs steps may be active at once on a node with the 
+\fBBULK_XFER\fR option due to limitations in the Federation switch driver.
+
 .TP 
 \fB\-\-nice\fR[=]<\fIadjustment\fR>
 Run the job with an adjusted scheduling priority within SLURM.
@@ -702,6 +717,9 @@ Same as \fB\-\-conn\-type\fR.
 \fBSBATCH_DEBUG\fR
 Same as \fB\-v\fR or \fB\-\-verbose\fR.
 .TP
+\fBSBATCH_DISTRIBUTION\fR
+Same as \fB\-m\fR or \fB\-\-distribution\fR.
+.TP
 \fBSBATCH_EXCLUSIVE\fR
 Same as \fB\-\-exclusive\fR.
 .TP
@@ -717,6 +735,9 @@ Same as \fB\-\-jobid\fR.
 \fBSBATCH_JOB_NAME\fR
 Same as \fB\-J\fR or \fB\-\-job\-name\fR.
 .TP
+\fBSBATCH_NETWORK\fR
+Same as \fB\-\-network\fR.
+.TP
 \fBSBATCH_NO_REQUEUE\fR
 Same as \fB\-\-no\-requeue\fR.
 .TP
diff --git a/doc/man/man1/sreport.1 b/doc/man/man1/sreport.1
index e67311c9fec92a1a9ef82d517af9f06f70d23860..ac0d0b7d575c4618ebffa378daa052d22ea33a1c 100644
--- a/doc/man/man1/sreport.1
+++ b/doc/man/man1/sreport.1
@@ -7,29 +7,34 @@ sreport \- Used to generate reports from the slurm accounting data.
 \fBssreport\fR [\fIOPTIONS\fR...] [\fICOMMAND\fR...]
 
 .SH "DESCRIPTION"
-\fBssreport\fR is used to generator certain reports.  Right now
-sreport is a template that does not really do anything.  In the future
-it will provide a view into accounting data gathered from slurm via
+\fBssreport\fR is used to generate certain reports.  More can be added
+at any time.  It provides a view into accounting data gathered from slurm via
 the account information maintained within a database with the interface 
-being provided by \fBslurmdbd\fR (Slurm Database daemon).
+being provided by the \fBslurmdbd\fR (Slurm Database daemon).
 
 .SH "OPTIONS"
 
 .TP
+\fB\-a\fR, \fB\-\-all_clusters\fR
+Use all clusters instead of only cluster from where the command was run.
+
 \fB\-h\fR, \fB\-\-help\fR
 Print a help message describing the usage of \fBssreport\fR.
 This is equivalent to the \fBhelp\fR command.
 
 .TP
-\fB\-o\fR, \fB\-\-oneliner\fR
-Print information one line per record.
-This is equivalent to the \fBoneliner\fR command.
+\fB\-n\fR, \fB\-\-no_header\fR
+Don't display header when listing results.
 
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
 Print no warning or informational messages, only error messages.
 This is equivalent to the \fBquiet\fR command.
 
+.TP
+\fB\-p\fR, \fB\-\-parsable\fR
+Make output '|' delimited.
+
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
 Print detailed event logging. 
@@ -40,8 +45,7 @@ This is equivalent to the \fBverbose\fR command.
 Print version information and exit.
 This is equivalent to the \fBversion\fR command.
 
-.TP
-\fBCOMMANDS\fR
+.SH "COMMANDS"
 
 .TP
 \fBexit\fP
@@ -52,14 +56,6 @@ Identical to the \fBquit\fR command.
 \fBhelp\fP
 Display a description of sreport options and commands.
 
-.TP
-\fBhide\fP
-Do not display information about hidden or deleted entities. 
-
-.TP
-\fBoneliner\fP
-Print information one line per record.
-
 .TP
 \fBquiet\fP
 Print no warning or informational messages, only fatal error messages.
@@ -83,9 +79,93 @@ Display the version number of sreport being executed.
 \fB!!\fP
 Repeat the last command executed.
 
+.SH "REPORT TYPES"
+.TP
+\fBcluster\fP, \fBjob\fP, and \fBuser\fP
+
+.TP
+Various reports are as follows...
+     cluster - Utilization
+     job     - Sizes
+     user    - TopUsage
+
+.TP
+Each report type has various options...
+
+.TP
+COMMON FOR ALL TYPES
+.RS
+.TP
+.B All_Clusters
+Use all monitored clusters default is local cluster.
+.TP
+.B End=<OPT>
+Period ending for report. Default is 23:59:59 of previous day.
+.TP
+.B Format=<OPT>
+Comma separated list of fields to display in report.
+.TP
+.B Start=<OPT>
+Period start for report.  Default is 00:00:00 of previous day.
+.RE
+
+.TP
+CLUSTER
+.RS
+.TP
+.B Names=<OPT>
+List of clusters to include in report.  Default is local cluster.
+.RE
+
+.TP
+JOB    
+.RS
+.TP
+.B Accounts=<OPT>
+List of accounts to use for the report Default is all.
+.TP
+.B Clusters=<OPT>
+List of clusters to include in report.  Default is local cluster.
+.TP
+.B GID=<OPT>
+List of group ids to include in report.  Default is all.
+.TP
+.B Grouping=<OPT>
+Comma separated list of size groupings.   (i.e. 50,100,150 would group job cpu count 1-49, 50-99, 100-149, > 150).
+.TP
+.B Jobs=<OPT>
+List of jobs/steps to include in report.  Default is all.
+.TP
+.B Partitions=<OPT>
+List of partitions jobs ran on to include in report.  Default is all.
+.TP
+.B Users=<OPT>
+List of users jobs to include in report.  Default is all.
+.RE
+
+.TP
+USER
+.RS
+.TP
+.B Clusters=<OPT>
+List of clusters to include in report. Default is local cluster.
+.TP
+.B Group
+Group all accounts together for each user.  Default is a separate entry for each user and account reference.
+.TP
+.B Users=<OPT>
+List of users jobs to include in report.  Default is all.
+.RE
+
+
 .SH "EXAMPLES"
 .eo
 .br
+> sreport job sizes 
+.br
+> sreport cluster utilization 
+.br
+> sreport user top 
 .ec
 
 .SH "COPYING"
@@ -107,5 +187,4 @@ FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.
 
 .SH "SEE ALSO"
-\fBslurm.conf\fR(5)
 \fBslurmdbd\fR(8)
diff --git a/doc/man/man5/slurm.conf.5 b/doc/man/man5/slurm.conf.5
index 8e1db34460e306ef4545775de40e09d026b6a014..1d908839d3617961e8332bfce4b5b0734f8ddb19 100644
--- a/doc/man/man5/slurm.conf.5
+++ b/doc/man/man5/slurm.conf.5
@@ -1259,10 +1259,13 @@ The node configuration specified the following information:
 Name that SLURM uses to refer to a node (or base partition for 
 BlueGene systems). 
 Typically this would be the string that "/bin/hostname \-s" returns.
-It may also be the fully qualified domane name as returned by "/bin/hostname \-f"
-(e.g. "foo1.bar.com"), although that may prevent use of hostlist expressions
-(the numeric portion in brackets must be at the end of the string).
-Fully qualified domain names are incompatible with the
+It may also be the fully qualified domain name as returned by "/bin/hostname \-f"
+(e.g. "foo1.bar.com"), or any valid domain name associated with the host
+through the host database (/etc/hosts) or DNS, depending on the resolver
+settings.  Note that if the short form of the hostname is not used, it
+may prevent use of hostlist expressions (the numeric portion in brackets
+must be at the end of the string).
+Only short hostname forms are compatible with the
 switch/elan and switch/federation plugins at this time.
 It may also be an arbitrary string if \fBNodeHostname\fR is specified.
 If the \fBNodeName\fR is "DEFAULT", the values specified 
@@ -1279,9 +1282,12 @@ considered adjacent in the computer.
 \fBNodeHostname\fR
 Typically this would be the string that "/bin/hostname \-s" returns. 
 It may also be the fully qualified domain name as returned by "/bin/hostname \-f"
-(e.g. "foo1.bar.com"), although that may prevent use of hostlist expressions
-(the numeric portion in brackets must be at the end of the string).
-Fully qualified domain names are incompatible with the
+(e.g. "foo1.bar.com"), or any valid domain name associated with the host
+through the host database (/etc/hosts) or DNS, depending on the resolver
+settings.  Note that if the short form of the hostname is not used, it
+may prevent use of hostlist expressions (the numeric portion in brackets
+must be at the end of the string).
+Only short hostname forms are compatible with the
 switch/elan and switch/federation plugins at this time.
 A node range expression can be used to specify a set of nodes.
 If an expression is used, the number of nodes identified by 
diff --git a/slurm.spec b/slurm.spec
index 57293ea4226b70fef60806a0b4a08981af689668..ba9bc65bea7f458a8f142b0b57bb6155827ac616 100644
--- a/slurm.spec
+++ b/slurm.spec
@@ -1,4 +1,4 @@
-# $Id: slurm.spec 14267 2008-06-16 18:13:01Z jette $
+# $Id: slurm.spec 14366 2008-06-26 20:04:12Z da $
 #
 # Note that this package is not relocatable
 
@@ -16,6 +16,8 @@
 # --without pam      %_without_pam      1    don't require pam-devel RPM to be installed
 # --without readline %_without_readline 1    don't require readline-devel RPM to be installed
 # --with sgijob      %_with_sgijob      1    build proctrack-sgi-job RPM
+# --with mysql       %_with_mysql       1    require mysql support
+# --with postgres    %_with_postgres    1    require postgresql support
 
 #
 #  Allow defining --with and --without build options or %_with and %without in .rpmmacors
@@ -36,6 +38,11 @@
 %slurm_without_opt auth_none
 %slurm_without_opt debug
 
+# These options are only here to force there to be these on the build.  
+# If they are not set they will still be compiled if the packages exist.
+%slurm_without_opt mysql
+%slurm_without_opt postgres
+
 # Build with munge by default on all platforms (disable using --without munge)
 %slurm_with_opt munge
 
@@ -55,23 +62,23 @@
 %slurm_with_opt aix
 %endif
 
-# Build with sgijob on CHAOS systems
-#  (add elan too when it is available)
+# Build with sgijob, elan, and mysql plugins on CHAOS systems
 %if %{?chaos}0
+%slurm_with_opt mysql
 %slurm_with_opt sgijob
 %else
 %slurm_without_opt sgijob
 %endif
 
 Name:    slurm
-Version: 1.3.4
+Version: 1.3.5
 Release: 1%{?dist}
 
 Summary: Simple Linux Utility for Resource Management
 
 License: GPL 
 Group: System Environment/Base
-Source: slurm-1.3.4.tar.bz2
+Source: slurm-1.3.5.tar.bz2
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}
 URL: https://computing.llnl.gov/linux/slurm/
 
@@ -90,6 +97,14 @@ BuildRequires: readline-devel
 BuildRequires: openssl-devel >= 0.9.6 openssl >= 0.9.6
 %endif
 
+%if %{slurm_with mysql}
+BuildRequires: mysql-devel >= 5.0.0
+%endif
+
+%if %{slurm_with postgres}
+BuildRequires: postgresql-devel >= 8.0.0
+%endif
+
 %description 
 SLURM is an open source, fault-tolerant, and highly
 scalable cluster management and job scheduling system for Linux clusters
@@ -158,12 +173,15 @@ Requires: slurm authd
 SLURM authentication module for Brent Chun's authd
 %endif
 
+# This is named munge instead of auth-munge since there are 2 plugins in the
+# package.  auth-munge and crypto-munge
 %if %{slurm_with munge}
 %package munge
 Summary: SLURM authentication and crypto implementation using Munge
 Group: System Environment/Base
 Requires: slurm munge
 BuildRequires: munge-devel munge-libs
+Obsoletes: slurm-auth-munge
 %description munge
 SLURM authentication module for Chris Dunlap's Munge
 %endif
@@ -231,7 +249,7 @@ SLURM process tracking plugin for SGI job containers.
 #############################################################################
 
 %prep
-%setup -n slurm-1.3.4
+%setup -n slurm-1.3.5
 
 %build
 %configure --program-prefix=%{?_program_prefix:%{_program_prefix}} \
diff --git a/src/api/allocate.c b/src/api/allocate.c
index 192c15226658c91a3530b1a216d9dd1fa0061acf..96769c7c0477dd4c9e649e950193b744d42cbb8a 100644
--- a/src/api/allocate.c
+++ b/src/api/allocate.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  *  allocate.c - allocate nodes for a job or step with supplied contraints
- *  $Id: allocate.c 13722 2008-03-27 16:39:22Z jette $
+ *  $Id: allocate.c 14453 2008-07-08 20:26:18Z da $
  *****************************************************************************
  *  Copyright (C) 2002 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -739,7 +739,7 @@ _wait_for_allocation_response(uint32_t job_id, const listen_t *listen,
 	resource_allocation_response_msg_t *resp = NULL;
 	int errnum;
 
-	debug("job %u queued and waiting for resources", job_id);
+	info("job %u queued and waiting for resources", job_id);
 	if (_wait_for_alloc_rpc(listen, timeout, &resp) <= 0) {
 		errnum = errno;
 		/* Maybe the resource allocation response RPC got lost
@@ -760,6 +760,6 @@ _wait_for_allocation_response(uint32_t job_id, const listen_t *listen,
 			return NULL;
 		}
 	}
-
+	info("job %u has been allocated resources", job_id);
 	return resp;
 }
diff --git a/src/api/step_launch.c b/src/api/step_launch.c
index c74952d17373cd3d16c5e5632bd2f747ae47516a..61c100f4bee66090112b431f4fa201db3e00c40b 100644
--- a/src/api/step_launch.c
+++ b/src/api/step_launch.c
@@ -1011,6 +1011,7 @@ static int _launch_tasks(slurm_step_ctx_t *ctx,
 	ListIterator ret_itr;
 	ret_data_info_t *ret_data = NULL;
 	int rc = SLURM_SUCCESS;
+	int tot_rc = SLURM_SUCCESS;
 
 	debug("Entering _launch_tasks");
 	if (ctx->verbose_level) {
@@ -1048,6 +1049,7 @@ static int _launch_tasks(slurm_step_ctx_t *ctx,
 			error("Task launch failed on node %s: %m",
 			      ret_data->node_name);
 			rc = SLURM_ERROR;
+			tot_rc = rc;
 		} else {
 #if 0 /* only for debugging, might want to make this a callback */
 			errno = ret_data->err;
@@ -1058,6 +1060,9 @@ static int _launch_tasks(slurm_step_ctx_t *ctx,
 	}
 	list_iterator_destroy(ret_itr);
 	list_destroy(ret_list);
+
+	if(tot_rc != SLURM_SUCCESS)
+		return tot_rc;
 	return rc;
 }
 
diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c
index ac7ef16dfdea28d5d9d5d8e48a7677664f121a98..21a5b2d2a701edb722274cc7afdde38b27faae76 100644
--- a/src/common/assoc_mgr.c
+++ b/src/common/assoc_mgr.c
@@ -449,7 +449,7 @@ extern int assoc_mgr_is_user_acct_coord(void *db_conn,
 	}
 	itr = list_iterator_create(found_user->coord_accts);
 	while((acct = list_next(itr))) {
-		if(!strcmp(acct_name, acct->acct_name))
+		if(!strcmp(acct_name, acct->name))
 			break;
 	}
 	list_iterator_destroy(itr);
@@ -534,26 +534,25 @@ extern int assoc_mgr_update_local_assocs(acct_update_object_t *update)
 				break;
 			}
 			debug("updating assoc %u", rec->id);
-			if(object->fairshare != (uint32_t)NO_VAL) {
+			if(object->fairshare != NO_VAL) {
 				rec->fairshare = object->fairshare;
 			}
 
-			if(object->max_jobs != (uint32_t)NO_VAL) {
+			if(object->max_jobs != NO_VAL) {
 				rec->max_jobs = object->max_jobs;
 			}
 
-			if(object->max_nodes_per_job != (uint32_t)NO_VAL) {
+			if(object->max_nodes_per_job != NO_VAL) {
 				rec->max_nodes_per_job =
 					object->max_nodes_per_job;
 			}
 
-			if(object->max_wall_duration_per_job !=
-			   (uint32_t)NO_VAL) {
+			if(object->max_wall_duration_per_job != NO_VAL) {
 				rec->max_wall_duration_per_job =
 					object->max_wall_duration_per_job;
 			}
 
-			if(object->max_cpu_secs_per_job != (uint32_t)NO_VAL) {
+			if(object->max_cpu_secs_per_job != NO_VAL) {
 				rec->max_cpu_secs_per_job = 
 					object->max_cpu_secs_per_job;
 			}
@@ -570,7 +569,6 @@ extern int assoc_mgr_update_local_assocs(acct_update_object_t *update)
 				
 			}
 			log_assoc_rec(rec);
-			/* FIX ME: do more updates here */
 			break;
 		case ACCT_ADD_ASSOC:
 			if(rec) {
@@ -579,6 +577,7 @@ extern int assoc_mgr_update_local_assocs(acct_update_object_t *update)
 			}
 			_set_assoc_parent_and_user(object);
 			list_append(local_association_list, object);
+			break;
 		case ACCT_REMOVE_ASSOC:
 			if(!rec) {
 				//rc = SLURM_ERROR;
@@ -672,7 +671,7 @@ extern int assoc_mgr_update_local_users(acct_update_object_t *update)
 			if(passwd_ptr) 
 				object->uid = passwd_ptr->pw_uid;
 			else
-				object->uid = (uint32_t)NO_VAL;
+				object->uid = NO_VAL;
 
 			list_append(local_user_list, object);
 		case ACCT_REMOVE_USER:
@@ -683,6 +682,7 @@ extern int assoc_mgr_update_local_users(acct_update_object_t *update)
 			list_delete_item(itr);
 			break;
 		case ACCT_ADD_COORD:
+			/* same as ACCT_REMOVE_COORD */
 		case ACCT_REMOVE_COORD:
 			if(!rec) {
 				//rc = SLURM_ERROR;
diff --git a/src/common/env.c b/src/common/env.c
index 0d416a5a6297789ffa7efb8092ee17c9976703c1..bad0e3821456fdca0f0b05efcee2c95bee9a3a1c 100644
--- a/src/common/env.c
+++ b/src/common/env.c
@@ -640,13 +640,12 @@ int setup_env(env_t *env)
 		 * determine what command a user will execute. We could
 		 * possibly add a "srestart" command which would set
 		 * MP_POERESTART_ENV, but that presently seems unnecessary. */
+		/* setenvf(&env->env, "MP_POERESTART_ENV", res_env); */
 		if (debug_env)
 			debug_num = atoi(debug_env);
 		snprintf(res_env, sizeof(res_env), "SLURM_LL_API_DEBUG=%d",
 			debug_num);
 		
-		setenvf(&env->env, "MP_POERESTART_ENV", res_env);
-
 		/* Required for AIX/POE systems indicating pre-allocation */
 		setenvf(&env->env, "LOADLBATCH", "yes");
 		setenvf(&env->env, "LOADL_ACTIVE", "3.2.0");
@@ -1159,6 +1158,8 @@ static int _env_array_entry_splitter(const char *entry,
 	int len;
 
 	ptr = index(entry, '=');
+	if (ptr == NULL)	/* Bad parsing, no '=' found */
+		return 0;
 	len = ptr - entry;
 	if (len > name_len-1)
 		return 0;
@@ -1252,6 +1253,23 @@ static void _strip_cr_nl(char *line)
 	}
 }
 
+/* Return the net count of curly brackets in a string
+ * '{' adds one and '}' subtracts one (zero means it is balanced).
+ * Special case: return -1 if no open brackets are found */
+static int _bracket_cnt(char *value)
+{
+	int open_br = 0, close_br = 0, i;
+	for (i=0; value[i]; i++) {
+		if (value[i] == '{')
+			open_br++;
+		else if (value[i] == '}')
+			close_br++;
+	}
+	if (open_br == 0)
+		return -1;
+	return (open_br - close_br);
+}
+
 /*
  * Load user environment from a cache file located in
  * <state_save_location>/env_username
@@ -1288,8 +1306,24 @@ static char **_load_env_cache(const char *username)
 		_strip_cr_nl(line);
 		if (_env_array_entry_splitter(line, name, sizeof(name), 
 					      value, ENV_BUFSIZE) &&
-		    (!_discard_env(name, value)))
+		    (!_discard_env(name, value))) {
+			if (value[0] == '(') {
+				/* This is a bash function.
+				 * It may span multiple lines */
+				int bracket_cnt;
+				while ((bracket_cnt = _bracket_cnt(value))) {
+					if (!fgets(line, ENV_BUFSIZE, fp))
+						break;
+					_strip_cr_nl(line);
+					if ((strlen(value) + strlen(line)) >
+					    (sizeof(value) - 1))
+						break;
+					strcat(value, "\n");
+					strcat(value, line);
+				}
+			}
 			env_array_overwrite(&env, name, value);
+		}
 	}
 	xfree(line);
 	xfree(value);
@@ -1412,7 +1446,6 @@ char **env_array_user_default(const char *username, int timeout, int mode)
 		if ((rc = poll(&ufds, 1, timeleft)) <= 0) {
 			if (rc == 0) {
 				verbose("timeout waiting for /bin/su to complete");
-				kill(-child, 9);
 				break;
 			}
 			if ((errno == EINTR) || (errno == EAGAIN))
@@ -1447,6 +1480,21 @@ char **env_array_user_default(const char *username, int timeout, int mode)
 		}
 	}
 	close(fildes[0]);
+	for (config_timeout=0; ; config_timeout++) {
+		kill(-child, SIGKILL);	/* Typically a no-op */
+		if (config_timeout)
+			sleep(1);
+		if (waitpid(child, &rc, WNOHANG) > 0)
+			break;
+		if (config_timeout >= 2) {
+			/* Non-killable processes are indicative of file system
+			 * problems. The process will remain as a zombie, but 
+			 * slurmd/salloc/moab will not otherwise be effected. */
+			error("Failed to kill program loading user environment");
+			break;
+		}
+	}
+	
 	if (!found) {
 		error("Failed to load current user environment variables");
 		xfree(buffer);
@@ -1483,8 +1531,24 @@ char **env_array_user_default(const char *username, int timeout, int mode)
 		}
 		if (_env_array_entry_splitter(line, name, sizeof(name), 
 					      value, ENV_BUFSIZE) &&
-		    (!_discard_env(name, value)))
+		    (!_discard_env(name, value))) {
+			if (value[0] == '(') {
+				/* This is a bash function.
+				 * It may span multiple lines */
+				int bracket_cnt;
+				while ((bracket_cnt = _bracket_cnt(value))) {
+					line = strtok_r(NULL, "\n", &last);
+					if (!line)
+						break;
+					if ((strlen(value) + strlen(line)) >
+					    (sizeof(value) - 1))
+						break;
+					strcat(value, "\n");
+					strcat(value, line);
+				}
+			}
 			env_array_overwrite(&env, name, value);
+		}
 		line = strtok_r(NULL, "\n", &last);
 	}
 	xfree(value);
diff --git a/src/common/forward.c b/src/common/forward.c
index 05b62d6619a8f24f267fe9dc77f2351297f0eae7..f892f578b2ccd1355c056986f17690fb2d76bd0f 100644
--- a/src/common/forward.c
+++ b/src/common/forward.c
@@ -174,12 +174,15 @@ void *_forward_thread(void *arg)
 		if(fwd_msg->header.forward.cnt > 0) {
 			static int message_timeout = -1;
 			if (message_timeout < 0)
-				message_timeout = slurm_get_msg_timeout() * 1000;
+				message_timeout = 
+					slurm_get_msg_timeout() * 1000;
 			steps = (fwd_msg->header.forward.cnt+1) /
 				slurm_get_tree_width();
 			fwd_msg->timeout = (message_timeout*steps);
+/* 			info("got %d * %d = %d", message_timeout, steps, fwd_msg->timeout); */
 			steps++;
 			fwd_msg->timeout += (start_timeout*steps);
+/* 			info("now  + %d*%d = %d", start_timeout, steps, fwd_msg->timeout); */
 		}	
 		
 		ret_list = slurm_receive_msgs(fd, steps, fwd_msg->timeout);
@@ -349,6 +352,12 @@ extern int forward_msg(forward_struct_t *forward_struct,
 		forward_msg->ret_list = forward_struct->ret_list;
 		
 		forward_msg->timeout = forward_struct->timeout;
+		
+		if(forward_msg->timeout <= 0) {
+			/* convert secs to msec */
+			forward_msg->timeout  = slurm_get_msg_timeout() * 1000; 
+		}
+
 		forward_msg->notify = &forward_struct->notify;
 		forward_msg->forward_mutex = &forward_struct->forward_mutex;
 		forward_msg->buf_len = forward_struct->buf_len;
diff --git a/src/common/jobacct_common.h b/src/common/jobacct_common.h
index e785e9c94f96a74f8d8239b19aba2e83a2abc54f..bb373fd9de327dcdc73ad70755e51299efd7dc17 100644
--- a/src/common/jobacct_common.h
+++ b/src/common/jobacct_common.h
@@ -151,6 +151,12 @@ typedef struct {
 } jobacct_job_rec_t;
 
 typedef struct {
+	char    *account; /* This is a pointer to the account var inside
+			   * the jobacct_job_rec_t that contains this
+			   * step.  It is to be used only in the
+			   * client.  This should not be freed, packed
+			   * or unpacked
+			   */
 	uint32_t elapsed;
 	time_t end;
 	int32_t exitcode;
diff --git a/src/common/plugin.c b/src/common/plugin.c
index 772edb27508b2091e4725bbd94d6630393de7a28..143e82ee0c2d12e1292a29b231497ec4f9d4fa46 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -301,8 +301,8 @@ plugin_get_syms( plugin_handle_t plug,
                 if ( ptrs[ i ] ) 
 			++count;
 		else 
-			error("Couldn't find sym '%s' in the plugin",
-			      names[ i ]);
+			debug4("Couldn't find sym '%s' in the plugin",
+			       names[ i ]);
 	}
 
         return count;
diff --git a/src/common/print_fields.c b/src/common/print_fields.c
index 9beeffd5606f95896c35e6feedbb58159ae80fbc..398a8597f29c909389bfc91ded724f1babe5826c 100644
--- a/src/common/print_fields.c
+++ b/src/common/print_fields.c
@@ -109,8 +109,12 @@ extern void print_fields_str(type_t type, print_field_t *field, char *value)
 
 		if(print_fields_parsable_print)
 			printf("%s|", print_this);
-		else
+		else {
+			if(strlen(print_this) > field->len) 
+				print_this[field->len-1] = '+';
+
 			printf("%-*.*s ", field->len, field->len, print_this);
+		}
 		break;
 	default:
 		if(print_fields_parsable_print)
@@ -129,11 +133,11 @@ extern void print_fields_uint32(type_t type, print_field_t *field,
 		if(print_fields_parsable_print)
 			printf("%s|", field->name);
 		else
-			printf("%-*.*s ", field->len, field->len, field->name);
+			printf("%*.*s ", field->len, field->len, field->name);
 		break;
 	case SLURM_PRINT_UNDERSCORE:
 		if(!print_fields_parsable_print)
-			printf("%-*.*s ", field->len, field->len, 
+			printf("%*.*s ", field->len, field->len, 
 			       "---------------------------------------");
 		break;
 	case SLURM_PRINT_VALUE:
@@ -142,7 +146,7 @@ extern void print_fields_uint32(type_t type, print_field_t *field,
 			if(print_fields_parsable_print)
 				printf("|");	
 			else				
-				printf("%-*s ", field->len, " ");
+				printf("%*s ", field->len, " ");
 		} else {
 			if(print_fields_parsable_print)
 				printf("%u|", value);	
@@ -154,7 +158,7 @@ extern void print_fields_uint32(type_t type, print_field_t *field,
 		if(print_fields_parsable_print)
 			printf("%s|", "n/a");
 		else
-			printf("%-*.*s ", field->len, field->len, "n/a");
+			printf("%*.*s ", field->len, field->len, "n/a");
 		break;
 	}
 }
@@ -167,11 +171,11 @@ extern void print_fields_uint64(type_t type, print_field_t *field,
 		if(print_fields_parsable_print)
 			printf("%s|", field->name);
 		else
-			printf("%-*.*s ", field->len, field->len, field->name);
+			printf("%*.*s ", field->len, field->len, field->name);
 		break;
 	case SLURM_PRINT_UNDERSCORE:
 		if(!print_fields_parsable_print)
-			printf("%-*.*s ", field->len, field->len, 
+			printf("%*.*s ", field->len, field->len, 
 			       "---------------------------------------");
 		break;
 	case SLURM_PRINT_VALUE:
@@ -180,7 +184,7 @@ extern void print_fields_uint64(type_t type, print_field_t *field,
 			if(print_fields_parsable_print)
 				printf("|");	
 			else				
-				printf("%-*s ", field->len, " ");
+				printf("%*s ", field->len, " ");
 		} else {
 			if(print_fields_parsable_print)
 				printf("%llu|", (long long unsigned) value);	
@@ -193,7 +197,7 @@ extern void print_fields_uint64(type_t type, print_field_t *field,
 		if(print_fields_parsable_print)
 			printf("%s|", "n/a");
 		else
-			printf("%-*.*s ", field->len, field->len, "n/a");
+			printf("%*.*s ", field->len, field->len, "n/a");
 		break;
 	}
 }
@@ -205,11 +209,11 @@ extern void print_fields_time(type_t type, print_field_t *field, uint32_t value)
 		if(print_fields_parsable_print)
 			printf("%s|", field->name);
 		else
-			printf("%-*.*s ", field->len, field->len, field->name);
+			printf("%*.*s ", field->len, field->len, field->name);
 		break;
 	case SLURM_PRINT_UNDERSCORE:
 		if(!print_fields_parsable_print)
-			printf("%-*.*s ", field->len, field->len, 
+			printf("%*.*s ", field->len, field->len, 
 			       "---------------------------------------");
 		break;
 	case SLURM_PRINT_VALUE:
@@ -218,7 +222,7 @@ extern void print_fields_time(type_t type, print_field_t *field, uint32_t value)
 			if(print_fields_parsable_print)
 				printf("|");	
 			else
-				printf("%-*s ", field->len, " ");
+				printf("%*s ", field->len, " ");
 		} else {
 			char time_buf[32];
 			mins2time_str((time_t) value, 
@@ -230,8 +234,62 @@ extern void print_fields_time(type_t type, print_field_t *field, uint32_t value)
 		}
 		break;
 	default:
-		printf("%-*.*s ", field->len, field->len, "n/a");
+		printf("%*.*s ", field->len, field->len, "n/a");
 		break;
 	}
 }
 
+extern void print_fields_char_list(type_t type, print_field_t *field,
+				   List value)
+{
+	ListIterator itr = NULL;
+	char *print_this = NULL;
+	char *object = NULL;
+	
+	switch(type) {
+	case SLURM_PRINT_HEADLINE:
+		if(print_fields_parsable_print)
+			printf("%s|", field->name);
+		else
+			printf("%-*.*s ", field->len, field->len, field->name);
+		break;
+	case SLURM_PRINT_UNDERSCORE:
+		if(!print_fields_parsable_print)
+			printf("%-*.*s ", field->len, field->len, 
+			       "---------------------------------------");
+		break;
+	case SLURM_PRINT_VALUE:
+		if(!value || !list_count(value)) {
+			if(print_fields_parsable_print)
+				print_this = xstrdup("");
+			else
+				print_this = xstrdup(" ");
+		} else {
+			itr = list_iterator_create(value);
+			while((object = list_next(itr))) {
+				if(print_this) 
+					xstrfmtcat(print_this, ",%s", object);
+				else 
+					print_this = xstrdup(object);
+			}
+			list_iterator_destroy(itr);
+		}
+
+		if(print_fields_parsable_print)
+			printf("%s|", print_this);
+		else {
+			if(strlen(print_this) > field->len) 
+				print_this[field->len-1] = '+';
+			
+			printf("%-*.*s ", field->len, field->len, print_this);
+		}
+		xfree(print_this);
+		break;
+	default:
+		if(print_fields_parsable_print)
+			printf("%s|", "n/a");
+		else
+			printf("%-*s ", field->len, "n/a");
+		break;
+	}
+}
diff --git a/src/common/print_fields.h b/src/common/print_fields.h
index 0a4e2c04657bb7c281ca9f95c1e7314283a2dcc9..9264970a6de7e45e94694af725607d669d0f0a82 100644
--- a/src/common/print_fields.h
+++ b/src/common/print_fields.h
@@ -93,6 +93,8 @@ extern void print_fields_uint64(type_t type, print_field_t *field,
 				uint64_t value);
 extern void print_fields_time(type_t type, print_field_t *field,
 			      uint32_t value);
+extern void print_fields_char_list(type_t type, print_field_t *field,
+				   List value);
 
 #define print_fields_uint print_fields_uint32
 #endif
diff --git a/src/common/read_config.c b/src/common/read_config.c
index 90598831f0302859a92425605b260e1ba173eadb..724caa3e10bc88c9a36ef2ece883395a6efc2a77 100644
--- a/src/common/read_config.c
+++ b/src/common/read_config.c
@@ -861,14 +861,6 @@ static void _init_slurmd_nodehash(void)
 	}
 }
 
-extern void slurm_conf_nodehash_init(void)
-{
-	slurm_conf_lock();
-	_init_slurmd_nodehash();
-	slurm_conf_unlock();
-}
-
-
 /*
  * Caller needs to call slurm_conf_lock() and hold the lock before
  * calling this function (and call slurm_conf_unlock() afterwards).
diff --git a/src/common/slurm_accounting_storage.c b/src/common/slurm_accounting_storage.c
index f7f545d37766e50fd5c94350f3f9a14e423d1ddd..597a7ee5befa4034ab7ce1367bb83061a0c4114c 100644
--- a/src/common/slurm_accounting_storage.c
+++ b/src/common/slurm_accounting_storage.c
@@ -191,7 +191,7 @@ static slurm_acct_storage_ops_t * _acct_storage_get_ops(
 		"acct_storage_p_add_clusters",
 		"acct_storage_p_add_associations",
 		"acct_storage_p_modify_users",
-		"acct_storage_p_modify_accts",
+		"acct_storage_p_modify_accounts",
 		"acct_storage_p_modify_clusters",
 		"acct_storage_p_modify_associations",
 		"acct_storage_p_remove_users",
@@ -353,7 +353,7 @@ extern void destroy_acct_coord_rec(void *object)
 		(acct_coord_rec_t *)object;
 
 	if(acct_coord) {
-		xfree(acct_coord->acct_name);
+		xfree(acct_coord->name);
 		xfree(acct_coord);
 	}
 }
@@ -638,7 +638,7 @@ unpack_error:
 }
 extern void pack_acct_account_rec(void *in, Buf buffer)
 {
-	char *coord = NULL;
+	acct_coord_rec_t *coord = NULL;
 	ListIterator itr = NULL;
 	uint32_t count = 0;
 	acct_account_rec_t *object = (acct_account_rec_t *)in;
@@ -674,7 +674,7 @@ extern void pack_acct_account_rec(void *in, Buf buffer)
 	if(count) {
 		itr = list_iterator_create(object->coordinators);
 		while((coord = list_next(itr))) {
-			packstr(coord, buffer);
+			pack_acct_coord_rec(coord, buffer);
 		}
 		list_iterator_destroy(itr);
 	}
@@ -691,7 +691,7 @@ extern int unpack_acct_account_rec(void **object, Buf buffer)
 	uint32_t uint32_tmp;
 	int i;
 	uint32_t count;
-	char *coord = NULL;
+	acct_coord_rec_t *coord = NULL;
 	acct_association_rec_t *assoc = NULL;
 	acct_account_rec_t *object_ptr = xmalloc(sizeof(acct_account_rec_t));
 
@@ -710,9 +710,11 @@ extern int unpack_acct_account_rec(void **object, Buf buffer)
 	}
 	safe_unpack32(&count, buffer);
 	if(count) {
-		object_ptr->coordinators = list_create(slurm_destroy_char);
+		object_ptr->coordinators = list_create(destroy_acct_coord_rec);
 		for(i=0; i<count; i++) {
-			safe_unpackstr_xmalloc(&coord, &uint32_tmp, buffer);
+			if(unpack_acct_coord_rec((void *)&coord, buffer)
+			   == SLURM_ERROR)
+				goto unpack_error;
 			list_append(object_ptr->coordinators, coord);
 		}
 	}
@@ -739,8 +741,8 @@ extern void pack_acct_coord_rec(void *in, Buf buffer)
 		return;
 	}
 
-	packstr(object->acct_name, buffer);
-	pack16(object->sub_acct, buffer);
+	packstr(object->name, buffer);
+	pack16(object->direct, buffer);
 }
 
 extern int unpack_acct_coord_rec(void **object, Buf buffer)
@@ -749,8 +751,8 @@ extern int unpack_acct_coord_rec(void **object, Buf buffer)
 	acct_coord_rec_t *object_ptr = xmalloc(sizeof(acct_coord_rec_t));
 
 	*object = object_ptr;
-	safe_unpackstr_xmalloc(&object_ptr->acct_name, &uint32_tmp, buffer);
-	safe_unpack16(&object_ptr->sub_acct, buffer);
+	safe_unpackstr_xmalloc(&object_ptr->name, &uint32_tmp, buffer);
+	safe_unpack16(&object_ptr->direct, buffer);
 	return SLURM_SUCCESS;
 
 unpack_error:
@@ -1146,6 +1148,7 @@ extern void pack_acct_account_cond(void *in, Buf buffer)
 		pack16(0, buffer);
 		pack16(0, buffer);
 		pack16(0, buffer);
+		pack16(0, buffer);
 		return;
 	}
  	if(object->acct_list)
@@ -1192,6 +1195,7 @@ extern void pack_acct_account_cond(void *in, Buf buffer)
 	}
 	pack16((uint16_t)object->qos, buffer);
 	pack16((uint16_t)object->with_assocs, buffer);
+	pack16((uint16_t)object->with_coords, buffer);
 	pack16((uint16_t)object->with_deleted, buffer);
 }
 
@@ -1235,6 +1239,7 @@ extern int unpack_acct_account_cond(void **object, Buf buffer)
 	}
 	safe_unpack16((uint16_t *)&object_ptr->qos, buffer);
 	safe_unpack16((uint16_t *)&object_ptr->with_assocs, buffer);
+	safe_unpack16((uint16_t *)&object_ptr->with_coords, buffer);
 	safe_unpack16((uint16_t *)&object_ptr->with_deleted, buffer);
 
 	return SLURM_SUCCESS;
@@ -1336,6 +1341,8 @@ extern void pack_acct_association_cond(void *in, Buf buffer)
 		pack32(0, buffer);
 		pack16(0, buffer);
 		pack16(0, buffer);
+		pack16(0, buffer);
+		pack16(0, buffer);
 		return;
 	}
 
@@ -1417,6 +1424,8 @@ extern void pack_acct_association_cond(void *in, Buf buffer)
 
 	pack16((uint16_t)object->with_usage, buffer);
 	pack16((uint16_t)object->with_deleted, buffer);
+	pack16((uint16_t)object->without_parent_info, buffer);
+	pack16((uint16_t)object->without_parent_limits, buffer);
 }
 
 extern int unpack_acct_association_cond(void **object, Buf buffer)
@@ -1486,7 +1495,9 @@ extern int unpack_acct_association_cond(void **object, Buf buffer)
 	}
 
 	safe_unpack16(&object_ptr->with_usage, buffer);
-	safe_unpack16((uint16_t *)&object_ptr->with_deleted, buffer);
+	safe_unpack16(&object_ptr->with_deleted, buffer);
+	safe_unpack16(&object_ptr->without_parent_info, buffer);
+	safe_unpack16(&object_ptr->without_parent_limits, buffer);
 	return SLURM_SUCCESS;
 
 unpack_error:
diff --git a/src/common/slurm_accounting_storage.h b/src/common/slurm_accounting_storage.h
index d3c204d81c8b2fdcc7798383e7ad8af09ba2b9e7..43cac986a4829bc3edfa11465067d8f2fef8c6a9 100644
--- a/src/common/slurm_accounting_storage.h
+++ b/src/common/slurm_accounting_storage.h
@@ -92,8 +92,11 @@ typedef struct {
 	uint32_t usage_end; 
 	uint32_t usage_start; 
 	List user_list;		/* list of char * */
-	uint16_t with_usage; 
-	uint16_t with_deleted; 
+	uint16_t with_usage;  /* fill in usage */
+	uint16_t with_deleted; /* return deleted associations */
+	uint16_t without_parent_info; /* don't give me parent id/name */
+	uint16_t without_parent_limits; /* don't give me limits from
+					 * parents */
 } acct_association_cond_t;
 
 typedef struct {
@@ -103,12 +106,13 @@ typedef struct {
 	List organization_list; /* list of char * */
 	acct_qos_level_t qos;	
 	uint16_t with_assocs; 
+	uint16_t with_coords; 
 	uint16_t with_deleted; 
 } acct_account_cond_t;
 
 typedef struct {
 	List assoc_list; /* list of acct_association_rec_t *'s */
-	List coordinators; /* list of char *'s */
+	List coordinators; /* list of acct_coord_rec_t *'s */
 	char *description;
 	char *name;
 	char *organization;
@@ -181,8 +185,8 @@ typedef struct {
 } acct_cluster_rec_t;
 
 typedef struct {
-	char *acct_name;
-	uint16_t sub_acct;
+	char *name;
+	uint16_t direct;
 } acct_coord_rec_t;
 
 typedef struct {
diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c
index 42473f1664913d972e90b8f40ff181a4ad35cfee..139b8e4445462058b045a5644eed5b843ddcf13b 100644
--- a/src/common/slurm_protocol_api.c
+++ b/src/common/slurm_protocol_api.c
@@ -641,18 +641,20 @@ static char *_global_auth_key(void)
 {
 	static bool loaded_storage_pass = false;
 	static char storage_pass[512] = "\0";
+	static char *storage_pass_ptr = NULL;
 	slurm_ctl_conf_t *conf;
 
 	if(loaded_storage_pass)
-		return storage_pass;
+		return storage_pass_ptr;
 
 	if(slurmdbd_conf) {
-		if(slurmdbd_conf->storage_pass) {
-			if(strlen(slurmdbd_conf->storage_pass) > 
+		if(slurmdbd_conf->auth_info) {
+			if(strlen(slurmdbd_conf->auth_info) > 
 			   sizeof(storage_pass))
-				fatal("StoragePass is too long");
-			strncpy(storage_pass, slurmdbd_conf->storage_pass, 
+				fatal("AuthInfo is too long");
+			strncpy(storage_pass, slurmdbd_conf->auth_info, 
 				sizeof(storage_pass));
+			storage_pass_ptr = storage_pass;
 		}
 	} else {
 		conf = slurm_conf_lock();
@@ -662,11 +664,12 @@ static char *_global_auth_key(void)
 				fatal("AccountingStoragePass is too long");
 			strncpy(storage_pass, conf->accounting_storage_pass, 
 				sizeof(storage_pass));
+			storage_pass_ptr = storage_pass;
 		}
 		slurm_conf_unlock();
 	}
 	loaded_storage_pass = true;
-	return storage_pass;
+	return storage_pass_ptr;
 }
 
 /* slurm_get_accounting_storage_port
@@ -1470,6 +1473,9 @@ List slurm_receive_msgs(slurm_fd fd, int steps, int timeout)
 
 	debug4("orig_timeout was %d we have %d steps and a timeout of %d",
 	       orig_timeout, steps, timeout);
+	/* we compare to the orig_timeout here because that is really
+	 *  what we are going to wait for each step
+	 */
 	if(orig_timeout >= (slurm_get_msg_timeout() * 10000)) {
 		debug("slurm_receive_msgs: "
 		      "You are sending a message with timeout's greater "
@@ -1479,7 +1485,8 @@ List slurm_receive_msgs(slurm_fd fd, int steps, int timeout)
 	} else if(orig_timeout < 1000) {
 		debug("slurm_receive_msgs: "
 		      "You are sending a message with a very short timeout of "
-		      "%d milliseconds", timeout);
+		      "%d milliseconds each step in the tree has %d "
+		      "milliseconds", timeout, orig_timeout);
 	} 
 	
 
diff --git a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c
index a2a5d5177ad9b5ffd8bb32df5ea4414e7f0c64df..58b4cf5f00a20a38e7b65b8fb35c6fbbb510b2b5 100644
--- a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c
+++ b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c
@@ -281,9 +281,9 @@ extern List acct_storage_p_modify_users(void *db_conn, uint32_t uid,
 	return SLURM_SUCCESS;
 }
 
-extern List acct_storage_p_modify_accts(void *db_conn, uint32_t uid,
-				       acct_account_cond_t *acct_q,
-				       acct_account_rec_t *acct)
+extern List acct_storage_p_modify_accounts(void *db_conn, uint32_t uid,
+					   acct_account_cond_t *acct_q,
+					   acct_account_rec_t *acct)
 {
 	return SLURM_SUCCESS;
 }
diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
index 2e3ea135692df0275443b2b5a5e9ff97c94c1880..1230c413cd91397dfa6b3b497268b86f209d8c8a 100644
--- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
+++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c
@@ -483,36 +483,36 @@ static int _modify_unset_users(mysql_conn_t *mysql_conn,
 		mod_assoc = xmalloc(sizeof(acct_association_rec_t));
 		mod_assoc->id = atoi(row[ASSOC_ID]);
 
-		if(!row[ASSOC_MJ] && assoc->max_jobs != (uint32_t)NO_VAL) {
+		if(!row[ASSOC_MJ] && assoc->max_jobs != NO_VAL) {
 			mod_assoc->max_jobs = assoc->max_jobs;
 			modified = 1;
 		} else
-			mod_assoc->max_jobs = (uint32_t)NO_VAL;
+			mod_assoc->max_jobs = NO_VAL;
 		
 		if(!row[ASSOC_MNPJ] &&
-		   assoc->max_nodes_per_job != (uint32_t)NO_VAL) {
+		   assoc->max_nodes_per_job != NO_VAL) {
 			mod_assoc->max_nodes_per_job =
 				assoc->max_nodes_per_job;
 			modified = 1;
 		} else 
-			mod_assoc->max_nodes_per_job = (uint32_t)NO_VAL;
+			mod_assoc->max_nodes_per_job = NO_VAL;
 
 		
 		if(!row[ASSOC_MWPJ] && 
-		   assoc->max_wall_duration_per_job != (uint32_t)NO_VAL) {
+		   assoc->max_wall_duration_per_job != NO_VAL) {
 			mod_assoc->max_wall_duration_per_job =
 				assoc->max_wall_duration_per_job;
 			modified = 1;
 		} else 
-			mod_assoc->max_wall_duration_per_job = (uint32_t)NO_VAL;
+			mod_assoc->max_wall_duration_per_job = NO_VAL;
 					
 		if(!row[ASSOC_MCPJ] && 
-		   assoc->max_cpu_secs_per_job != (uint32_t)NO_VAL) {
+		   assoc->max_cpu_secs_per_job != NO_VAL) {
 			mod_assoc->max_cpu_secs_per_job = 
 				assoc->max_cpu_secs_per_job;
 			modified = 1;
 		} else
-			mod_assoc->max_cpu_secs_per_job = (uint32_t)NO_VAL;
+			mod_assoc->max_cpu_secs_per_job = NO_VAL;
 		
 
 		if(modified) {
@@ -527,7 +527,7 @@ static int _modify_unset_users(mysql_conn_t *mysql_conn,
 				continue;
 			}
 
-			mod_assoc->fairshare = (uint32_t)NO_VAL;
+			mod_assoc->fairshare = NO_VAL;
 			if(row[ASSOC_PART][0]) { 
 				// see if there is a partition name
 				object = xstrdup_printf(
@@ -616,9 +616,7 @@ static int _remove_common(mysql_conn_t *mysql_conn,
 			if(mysql_conn->rollback) {
 				mysql_db_rollback(mysql_conn->acct_mysql_db);
 			}
-			list_destroy(mysql_conn->update_list);
-			mysql_conn->update_list =
-				list_create(destroy_acct_update_object);
+			list_flush(mysql_conn->update_list);
 			return SLURM_ERROR;
 		}
 
@@ -640,9 +638,7 @@ static int _remove_common(mysql_conn_t *mysql_conn,
 			if(mysql_conn->rollback) {
 				mysql_db_rollback(mysql_conn->acct_mysql_db);
 			}
-			list_destroy(mysql_conn->update_list);
-			mysql_conn->update_list =
-				list_create(destroy_acct_update_object);
+			list_flush(mysql_conn->update_list);
 			return SLURM_ERROR;
 		}
 		xfree(query);
@@ -800,6 +796,62 @@ static int _remove_common(mysql_conn_t *mysql_conn,
 	return rc;
 }
 
+static int _get_account_coords(mysql_conn_t *mysql_conn, 
+			       acct_account_rec_t *acct)
+{
+	char *query = NULL;
+	acct_coord_rec_t *coord = NULL;
+	MYSQL_RES *result = NULL;
+	MYSQL_ROW row;
+	
+	if(!acct) {
+		error("We need a account to fill in.");
+		return SLURM_ERROR;
+	}
+
+	if(!acct->coordinators)
+		acct->coordinators = list_create(destroy_acct_coord_rec);
+			
+	query = xstrdup_printf(
+		"select user from %s where acct='%s' && deleted=0",
+		acct_coord_table, acct->name);
+			
+	if(!(result =
+	     mysql_db_query_ret(mysql_conn->acct_mysql_db, query, 0))) {
+		xfree(query);
+		return SLURM_ERROR;
+	}
+	xfree(query);
+	while((row = mysql_fetch_row(result))) {
+		coord = xmalloc(sizeof(acct_coord_rec_t));
+		list_append(acct->coordinators, coord);
+		coord->name = xstrdup(row[0]);
+		coord->direct = 1;
+	}
+	mysql_free_result(result);
+		
+	query = xstrdup_printf("select distinct t0.user from %s as t0, "
+			       "%s as t1, %s as t2 where t0.acct=t1.acct && "
+			       "t1.lft<t2.lft && t1.rgt>t2.lft && "
+			       "t1.user='' && t2.acct='%s' && t1.acct!='%s' && "
+			       "!t0.deleted;",
+			       acct_coord_table, assoc_table, assoc_table,
+			       acct->name, acct->name);
+	if(!(result =
+	     mysql_db_query_ret(mysql_conn->acct_mysql_db, query, 0))) {
+		xfree(query);
+		return SLURM_ERROR;
+	}
+	xfree(query);
+	while((row = mysql_fetch_row(result))) {
+		coord = xmalloc(sizeof(acct_coord_rec_t));
+		list_append(acct->coordinators, coord);
+		coord->name = xstrdup(row[0]);
+		coord->direct = 0;
+	}
+	return SLURM_SUCCESS;
+}
+
 static int _get_user_coords(mysql_conn_t *mysql_conn, acct_user_rec_t *user)
 {
 	char *query = NULL;
@@ -829,8 +881,8 @@ static int _get_user_coords(mysql_conn_t *mysql_conn, acct_user_rec_t *user)
 	while((row = mysql_fetch_row(result))) {
 		coord = xmalloc(sizeof(acct_coord_rec_t));
 		list_append(user->coord_accts, coord);
-		coord->acct_name = xstrdup(row[0]);
-		coord->sub_acct = 0;
+		coord->name = xstrdup(row[0]);
+		coord->direct = 1;
 		if(query) 
 			xstrcat(query, " || ");
 		else 
@@ -846,7 +898,7 @@ static int _get_user_coords(mysql_conn_t *mysql_conn, acct_user_rec_t *user)
 			   "&& t1.lft between t2.lft "
 			   "and t2.rgt && t1.user='' "
 			   "&& t1.acct!='%s')",
-			   coord->acct_name, coord->acct_name);
+			   coord->name, coord->name);
 	}
 	mysql_free_result(result);
 
@@ -862,7 +914,7 @@ static int _get_user_coords(mysql_conn_t *mysql_conn, acct_user_rec_t *user)
 		while((row = mysql_fetch_row(result))) {
 
 			while((coord = list_next(itr))) {
-				if(!strcmp(coord->acct_name, row[0]))
+				if(!strcmp(coord->name, row[0]))
 					break;
 			}
 			list_iterator_reset(itr);
@@ -871,8 +923,8 @@ static int _get_user_coords(mysql_conn_t *mysql_conn, acct_user_rec_t *user)
 					
 			coord = xmalloc(sizeof(acct_coord_rec_t));
 			list_append(user->coord_accts, coord);
-			coord->acct_name = xstrdup(row[0]);
-			coord->sub_acct = 1;
+			coord->name = xstrdup(row[0]);
+			coord->direct = 0;
 		}
 		list_iterator_destroy(itr);
 		mysql_free_result(result);
@@ -1111,7 +1163,7 @@ static int _mysql_acct_check_tables(MYSQL *acct_mysql_db)
 	char *get_parent_proc = 
 		"drop procedure if exists get_parent_limits; "
 		"create procedure get_parent_limits("
-		"my_table text, acct text, cluster text) "
+		"my_table text, acct text, cluster text, without_limits int) "
 		"begin "
 		"set @par_id = NULL; "
 		"set @mj = NULL; "
@@ -1119,6 +1171,12 @@ static int _mysql_acct_check_tables(MYSQL *acct_mysql_db)
 		"set @mwpj = NULL; "
 		"set @mcpj = NULL; "
 		"set @my_acct = acct; "
+		"if without_limits then "
+		"set @mj = 0; " 
+		"set @mnpj = 0; "
+		"set @mwpj = 0; "
+		"set @mcpj = 0; "
+		"end if; "
 		"REPEAT "
 		"set @s = 'select '; "
 		"if @par_id is NULL then set @s = CONCAT("
@@ -1260,7 +1318,8 @@ extern int init ( void )
 	char *location = NULL;
 #else
 	fatal("No MySQL database was found on the machine. "
-	      "Please check the configure log and run again.");
+	      "Please check the config.log from the run of configure "
+	      "and run again.");
 #endif
 
 	/* since this can be loaded from many different places
@@ -1836,6 +1895,7 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 	struct passwd *pw = NULL;
 	char *user = NULL;
 	int affect_rows = 0;
+	int added = 0;
 
 	if(_check_connection(mysql_conn) != SLURM_SUCCESS)
 		return SLURM_ERROR;
@@ -1862,7 +1922,7 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 			xstrfmtcat(vals, ", %u", object->default_fairshare);
 			xstrfmtcat(extra, ", fairshare=%u",
 				   object->default_fairshare);
-		} else if ((int)object->default_fairshare == -1) {
+		} else if ((int)object->default_fairshare == INFINITE) {
 			xstrcat(cols, ", fairshare");
 			xstrfmtcat(vals, ", NULL");
 			xstrfmtcat(extra, ", fairshare=NULL");		
@@ -1874,7 +1934,7 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 				   object->default_max_cpu_secs_per_job);
 			xstrfmtcat(extra, ", max_cpu_secs_per_job=%u",
 				   object->default_max_cpu_secs_per_job);
-		} else if((int)object->default_max_cpu_secs_per_job == -1) {
+		} else if((int)object->default_max_cpu_secs_per_job == INFINITE) {
 			xstrcat(cols, ", max_cpu_secs_per_job");
 			xstrfmtcat(vals, ", NULL");
 			xstrfmtcat(extra, ", max_cpu_secs_per_job=NULL");
@@ -1885,7 +1945,7 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 			xstrfmtcat(vals, ", %u", object->default_max_jobs);
 			xstrfmtcat(extra, ", max_jobs=%u",
 				   object->default_max_jobs);
-		} else if((int)object->default_max_jobs == -1) {
+		} else if((int)object->default_max_jobs == INFINITE) {
 			xstrcat(cols, ", max_jobs");
 			xstrfmtcat(vals, ", NULL");
 			xstrfmtcat(extra, ", max_jobs=NULL");		
@@ -1897,7 +1957,7 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 				   object->default_max_nodes_per_job);
 			xstrfmtcat(extra, ", max_nodes_per_job=%u",
 				   object->default_max_nodes_per_job);
-		} else if((int)object->default_max_nodes_per_job == -1) {
+		} else if((int)object->default_max_nodes_per_job == INFINITE) {
 			xstrcat(cols, ", max_nodes_per_job");
 			xstrfmtcat(vals, ", NULL");
 			xstrfmtcat(extra, ", max_nodes_per_job=NULL");
@@ -1910,10 +1970,10 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 			xstrfmtcat(extra, ", max_wall_duration_per_job=%u",
 				   object->default_max_wall_duration_per_job);
 		} else if((int)object->default_max_wall_duration_per_job
-			  == -1) {
+			  == INFINITE) {
 			xstrcat(cols, ", max_wall_duration_per_job");
 			xstrfmtcat(vals, ", NULL");
-			xstrfmtcat(extra, ", max_duration_per_job=NULL");
+			xstrfmtcat(extra, ", max_wall_duration_per_job=NULL");
 		}
 
 		xstrfmtcat(query, 
@@ -1931,7 +1991,8 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 			xfree(extra);
 			xfree(cols);
 			xfree(vals);
-			continue;
+			added=0;
+			break;
 		}
 
 		affect_rows = _last_affected_rows(mysql_conn->acct_mysql_db);
@@ -1967,7 +2028,8 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 		if(rc != SLURM_SUCCESS) {
 			error("Couldn't add cluster root assoc");
 			xfree(extra);
-			continue;
+			added=0;
+			break;
 		}
 		xstrfmtcat(query,
 			   "insert into %s "
@@ -1981,10 +2043,18 @@ extern int acct_storage_p_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
 		xfree(query);
 		if(rc != SLURM_SUCCESS) {
 			error("Couldn't add txn");
-		}
+		} else
+			added++;
 	}
 	list_iterator_destroy(itr);
 
+	if(!added) {
+		if(mysql_conn->rollback) {
+			mysql_db_rollback(mysql_conn->acct_mysql_db);
+		}
+		list_flush(mysql_conn->update_list);
+	}
+
 	return rc;
 #else
 	return SLURM_ERROR;
@@ -2337,6 +2407,9 @@ extern int acct_storage_p_add_associations(mysql_conn_t *mysql_conn,
 		xfree(extra);
 	}
 	list_iterator_destroy(itr);
+	if(rc != SLURM_SUCCESS)
+		goto end_it;
+
 	if(incr) {
 		char *up_query = xstrdup_printf(
 			"UPDATE %s SET rgt = rgt+%d "
@@ -2359,6 +2432,7 @@ extern int acct_storage_p_add_associations(mysql_conn_t *mysql_conn,
 		
 	}
 
+end_it:
 	if(rc != SLURM_ERROR) {
 		if(txn_query) {
 			xstrcat(txn_query, ";");
@@ -2370,9 +2444,14 @@ extern int acct_storage_p_add_associations(mysql_conn_t *mysql_conn,
 				rc = SLURM_SUCCESS;
 			}
 		}
-	} else
+	} else {
 		xfree(txn_query);
-	
+		if(mysql_conn->rollback) {
+			mysql_db_rollback(mysql_conn->acct_mysql_db);
+		}
+		list_flush(mysql_conn->update_list);
+	}
+
 	xfree(old_parent);
 	xfree(old_cluster);
 					
@@ -2458,6 +2537,7 @@ extern List acct_storage_p_modify_users(mysql_conn_t *mysql_conn, uint32_t uid,
 		xstrfmtcat(vals, ", admin_level=%u", user->admin_level);
 
 	if(!extra || !vals) {
+		errno = SLURM_NO_CHANGE_IN_DATA;
 		error("Nothing to change");
 		return NULL;
 	}
@@ -2510,9 +2590,10 @@ extern List acct_storage_p_modify_users(mysql_conn_t *mysql_conn, uint32_t uid,
 #endif
 }
 
-extern List acct_storage_p_modify_accts(mysql_conn_t *mysql_conn, uint32_t uid, 
-					acct_account_cond_t *acct_q,
-					acct_account_rec_t *acct)
+extern List acct_storage_p_modify_accounts(
+	mysql_conn_t *mysql_conn, uint32_t uid, 
+	acct_account_cond_t *acct_q,
+	acct_account_rec_t *acct)
 {
 #ifdef HAVE_MYSQL
 	ListIterator itr = NULL;
@@ -2594,6 +2675,7 @@ extern List acct_storage_p_modify_accts(mysql_conn_t *mysql_conn, uint32_t uid,
 		xstrfmtcat(vals, ", qos='%u'", acct->qos);
 
 	if(!extra || !vals) {
+		errno = SLURM_NO_CHANGE_IN_DATA;
 		error("Nothing to change");
 		return NULL;
 	}
@@ -2638,6 +2720,7 @@ extern List acct_storage_p_modify_accts(mysql_conn_t *mysql_conn, uint32_t uid,
 	   == SLURM_ERROR) {
 		error("Couldn't modify accounts");
 		list_destroy(ret_list);
+		errno = SLURM_ERROR;
 		ret_list = NULL;
 	}
 		
@@ -2710,6 +2793,7 @@ extern List acct_storage_p_modify_clusters(mysql_conn_t *mysql_conn,
 	}
 
 	if(!vals) {
+		errno = SLURM_NO_CHANGE_IN_DATA;
 		error("Nothing to change");
 		return NULL;
 	}
@@ -2906,7 +2990,7 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 		list_iterator_destroy(itr);
 		xstrcat(extra, ")");
 	} else {
-		info("no user specified");
+		debug4("no user specified");
 		xstrcat(extra, " && user = '' ");
 	}
 
@@ -2930,33 +3014,35 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 
 	if((int)assoc->fairshare >= 0) 
 		xstrfmtcat(vals, ", fairshare=%u", assoc->fairshare);
-	else if((int)assoc->fairshare == -1) 
+	else if((int)assoc->fairshare == INFINITE) {
 		xstrfmtcat(vals, ", fairshare=1");
-       		
+		assoc->fairshare = 1;
+	}
 	if((int)assoc->max_cpu_secs_per_job >= 0) 
 		xstrfmtcat(vals, ", max_cpu_secs_per_job=%u",
 			   assoc->max_cpu_secs_per_job);
-	else if((int)assoc->max_cpu_secs_per_job == -1) 
+	else if((int)assoc->max_cpu_secs_per_job == INFINITE) {
 		xstrfmtcat(vals, ", max_cpu_secs_per_job=NULL");
-
+	}
 	if((int)assoc->max_jobs >= 0) 
 		xstrfmtcat(vals, ", max_jobs=%u", assoc->max_jobs);
-	else if((int)assoc->max_jobs == -1)
+	else if((int)assoc->max_jobs == INFINITE) {
 		xstrfmtcat(vals, ", max_jobs=NULL");
-		
+	}
 	if((int)assoc->max_nodes_per_job >= 0) 
 		xstrfmtcat(vals, ", max_nodes_per_job=%u",
 			   assoc->max_nodes_per_job);
-	else if((int)assoc->max_nodes_per_job == -1)
+	else if((int)assoc->max_nodes_per_job == INFINITE) {
 		xstrfmtcat(vals, ", max_nodes_per_job=NULL");
-
+	}
 	if((int)assoc->max_wall_duration_per_job >= 0) 
 		xstrfmtcat(vals, ", max_wall_duration_per_job=%u",
 			   assoc->max_wall_duration_per_job);
-	else if((int)assoc->max_wall_duration_per_job == -1) 
+	else if((int)assoc->max_wall_duration_per_job == INFINITE) {
 		xstrfmtcat(vals, ", max_wall_duration_per_job=NULL");
-		
+	}
 	if(!extra || (!vals && !assoc->parent_acct)) {
+		errno = SLURM_NO_CHANGE_IN_DATA;
 		error("Nothing to change");
 		return NULL;
 	}
@@ -2993,9 +3079,29 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 
 		if(!is_admin) {
 			acct_coord_rec_t *coord = NULL;
+			char *account = row[MASSOC_ACCT];
+
+			/* Here we want to see if the person
+			 * is a coord of the parent account
+			 * since we don't want him to be able
+			 * to alter the limits of the account
+			 * he is directly coord of.  They
+			 * should be able to alter the
+			 * sub-accounts though. If no parent account
+			 * that means we are talking about a user
+			 * association so account is really the parent
+			 * of the user a coord can change that all day long.
+			 */
+			if(row[MASSOC_PACCT][0])
+				account = row[MASSOC_PACCT];
+
 			if(!user.coord_accts) { // This should never
 						// happen
-				error("We are here with no coord accts");
+				error("We are here with no coord accts.");
+				if(mysql_conn->rollback) {
+					mysql_db_rollback(
+						mysql_conn->acct_mysql_db);
+				}
 				errno = ESLURM_ACCESS_DENIED;
 				mysql_free_result(result);
 				xfree(vals);
@@ -3004,16 +3110,36 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 			}
 			itr = list_iterator_create(user.coord_accts);
 			while((coord = list_next(itr))) {
-				if(!strcasecmp(coord->acct_name, row[1]))
+				if(!strcasecmp(coord->name, account))
 					break;
 			}
 			list_iterator_destroy(itr);
 
 			if(!coord) {
-				error("User %s(%d) does not have the "
-				      "ability to change this account (%s)",
-				      user.name, user.uid, row[1]);
-				continue;
+				if(row[MASSOC_PACCT][0])
+					error("User %s(%d) can not modify "
+					      "account (%s) because they "
+					      "are not coordinators of "
+					      "parent account '%s'.",
+					      user.name, user.uid,
+					      row[MASSOC_ACCT], 
+					      row[MASSOC_PACCT]);
+				else
+					error("User %s(%d) does not have the "
+					      "ability to modify the account "
+					      "(%s).",
+					      user.name, user.uid, 
+					      row[MASSOC_ACCT]);
+					
+				if(mysql_conn->rollback) {
+					mysql_db_rollback(
+						mysql_conn->acct_mysql_db);
+				}
+				errno = ESLURM_ACCESS_DENIED;
+				mysql_free_result(result);
+				xfree(vals);
+				list_destroy(ret_list);
+				return NULL;
 			}
 		}
 
@@ -3101,17 +3227,19 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 			if(mysql_conn->rollback) {
 				mysql_db_rollback(mysql_conn->acct_mysql_db);
 			}
-			list_destroy(mysql_conn->update_list);
-			mysql_conn->update_list =
-				list_create(destroy_acct_update_object);
+			list_flush(mysql_conn->update_list);
 			list_destroy(ret_list);
 			xfree(vals);
+			errno = rc;
 			return NULL;
 		}
 	}
 
 
 	if(!list_count(ret_list)) {
+		if(mysql_conn->rollback) {
+			mysql_db_rollback(mysql_conn->acct_mysql_db);
+		}
 		errno = SLURM_NO_CHANGE_IN_DATA;
 		debug3("didn't effect anything");
 		xfree(vals);
@@ -3123,6 +3251,10 @@ extern List acct_storage_p_modify_associations(mysql_conn_t *mysql_conn,
 		if(_modify_common(mysql_conn, DBD_MODIFY_ASSOCS, now,
 				  user_name, assoc_table, name_char, vals)
 		   == SLURM_ERROR) {
+			if(mysql_conn->rollback) {
+				mysql_db_rollback(mysql_conn->acct_mysql_db);
+			}
+			list_flush(mysql_conn->update_list);
 			error("Couldn't modify associations");
 			list_destroy(ret_list);
 			ret_list = NULL;
@@ -3255,7 +3387,7 @@ extern List acct_storage_p_remove_users(mysql_conn_t *mysql_conn, uint32_t uid,
 	xfree(name_char);
 
 	query = xstrdup_printf(
-		"update %s as t2, set deleted=1, mod_time=%d where %s",
+		"update %s as t2 set deleted=1, mod_time=%d where %s",
 		acct_coord_table, now, assoc_char);
 	xfree(assoc_char);
 
@@ -3402,7 +3534,7 @@ extern List acct_storage_p_remove_coord(mysql_conn_t *mysql_conn, uint32_t uid,
 			}
 			itr = list_iterator_create(user.coord_accts);
 			while((coord = list_next(itr))) {
-				if(!strcasecmp(coord->acct_name, row[1]))
+				if(!strcasecmp(coord->name, row[1]))
 					break;
 			}
 			list_iterator_destroy(itr);
@@ -3411,7 +3543,12 @@ extern List acct_storage_p_remove_coord(mysql_conn_t *mysql_conn, uint32_t uid,
 				error("User %s(%d) does not have the "
 				      "ability to change this account (%s)",
 				      user.name, user.uid, row[1]);
-				continue;
+				errno = ESLURM_ACCESS_DENIED;
+				list_destroy(ret_list);
+				list_destroy(user_list);
+				xfree(extra);
+				mysql_free_result(result);
+				return NULL;
 			}
 		}
 		if(!last_user || strcasecmp(last_user, row[0])) {
@@ -3896,6 +4033,10 @@ extern List acct_storage_p_remove_associations(mysql_conn_t *mysql_conn,
 	mysql_free_result(result);
 
 	if(!name_char) {
+		if(mysql_conn->rollback) {
+			mysql_db_rollback(mysql_conn->acct_mysql_db);
+		}
+		list_flush(mysql_conn->update_list);
 		errno = SLURM_NO_CHANGE_IN_DATA;
 		debug3("didn't effect anything\n%s", query);
 		xfree(query);
@@ -3912,6 +4053,10 @@ extern List acct_storage_p_remove_associations(mysql_conn_t *mysql_conn,
 	debug3("%d query\n%s", mysql_conn->conn, query);
 	if(!(result = mysql_db_query_ret(
 		     mysql_conn->acct_mysql_db, query, 0))) {
+		if(mysql_conn->rollback) {
+			mysql_db_rollback(mysql_conn->acct_mysql_db);
+		}
+		list_flush(mysql_conn->update_list);
 		xfree(query);
 		xfree(name_char);
 		return NULL;
@@ -3931,7 +4076,7 @@ extern List acct_storage_p_remove_associations(mysql_conn_t *mysql_conn,
 			}
 			itr = list_iterator_create(user.coord_accts);
 			while((coord = list_next(itr))) {
-				if(!strcasecmp(coord->acct_name,
+				if(!strcasecmp(coord->name,
 					       row[RASSOC_ACCT]))
 					break;
 			}
@@ -3941,7 +4086,8 @@ extern List acct_storage_p_remove_associations(mysql_conn_t *mysql_conn,
 				error("User %s(%d) does not have the "
 				      "ability to change this account (%s)",
 				      user.name, user.uid, row[RASSOC_ACCT]);
-				continue;
+				errno = ESLURM_ACCESS_DENIED;
+				goto end_it;
 			}
 		}
 		if(row[RASSOC_PART][0]) { 
@@ -3988,16 +4134,20 @@ extern List acct_storage_p_remove_associations(mysql_conn_t *mysql_conn,
 	if(_remove_common(mysql_conn, DBD_REMOVE_ASSOCS, now,
 			  user_name, assoc_table, name_char, assoc_char)
 	   == SLURM_ERROR) {
-		list_destroy(ret_list);
 		xfree(name_char);
 		xfree(assoc_char);
-		return NULL;
+		goto end_it;
 	}
 	xfree(name_char);
 	xfree(assoc_char);
 
 	return ret_list;
 end_it:
+	if(mysql_conn->rollback) {
+		mysql_db_rollback(mysql_conn->acct_mysql_db);
+	}
+	list_flush(mysql_conn->update_list);
+	
 	if(ret_list) {
 		list_destroy(ret_list);
 		ret_list = NULL;
@@ -4184,8 +4334,8 @@ extern List acct_storage_p_get_accts(mysql_conn_t *mysql_conn,
 	char *object = NULL;
 	int set = 0;
 	int i=0;
-	MYSQL_RES *result = NULL, *coord_result = NULL;
-	MYSQL_ROW row, coord_row;
+	MYSQL_RES *result = NULL;
+	MYSQL_ROW row;
 
 	/* if this changes you will need to edit the corresponding enum */
 	char *acct_req_inx[] = {
@@ -4297,23 +4447,9 @@ empty:
 		acct->organization = xstrdup(row[ACCT_REQ_ORG]);
 		acct->qos = atoi(row[ACCT_REQ_QOS]);
 
-		acct->coordinators = list_create(slurm_destroy_char);
-		query = xstrdup_printf("select user from %s where acct='%s' "
-				       "&& deleted=0;",
-				       acct_coord_table, acct->name);
-
-		if(!(coord_result =
-		     mysql_db_query_ret(mysql_conn->acct_mysql_db, query, 0))) {
-			xfree(query);
-			continue;
-		}
-		xfree(query);
-		
-		while((coord_row = mysql_fetch_row(coord_result))) {
-			object = xstrdup(coord_row[0]);
-			list_append(acct->coordinators, object);
+		if(acct_q && acct_q->with_coords) {
+			_get_account_coords(mysql_conn, acct);
 		}
-		mysql_free_result(coord_result);
 
 		if(acct_q && acct_q->with_assocs) {
 			acct_association_cond_t *assoc_q = NULL;
@@ -4480,25 +4616,25 @@ empty:
 		if(row2[ASSOC_REQ_MJ])
 			cluster->default_max_jobs = atoi(row2[ASSOC_REQ_MJ]);
 		else
-			cluster->default_max_jobs = -1;
+			cluster->default_max_jobs = INFINITE;
 		
 		if(row2[ASSOC_REQ_MNPJ])
 			cluster->default_max_nodes_per_job =
 				atoi(row2[ASSOC_REQ_MNPJ]);
 		else
-			cluster->default_max_nodes_per_job = -1;
+			cluster->default_max_nodes_per_job = INFINITE;
 		
 		if(row2[ASSOC_REQ_MWPJ])
 			cluster->default_max_wall_duration_per_job = 
 				atoi(row2[ASSOC_REQ_MWPJ]);
 		else
-			cluster->default_max_wall_duration_per_job = -1;
+			cluster->default_max_wall_duration_per_job = INFINITE;
 		
 		if(row2[ASSOC_REQ_MCPJ])
 			cluster->default_max_cpu_secs_per_job = 
 				atoi(row2[ASSOC_REQ_MCPJ]);
 		else 
-			cluster->default_max_cpu_secs_per_job = -1;
+			cluster->default_max_cpu_secs_per_job = INFINITE;
 		mysql_free_result(result2);
 	}
 	mysql_free_result(result);
@@ -4524,13 +4660,14 @@ extern List acct_storage_p_get_associations(mysql_conn_t *mysql_conn,
 	int i=0;
 	MYSQL_RES *result = NULL;
 	MYSQL_ROW row;
-	int parent_mj = -1;
-	int parent_mnpj = -1;
-	int parent_mwpj = -1;
-	int parent_mcpj = -1;
+	int parent_mj = INFINITE;
+	int parent_mnpj = INFINITE;
+	int parent_mwpj = INFINITE;
+	int parent_mcpj = INFINITE;
 	char *last_acct = NULL;
 	char *last_acct_parent = NULL;
 	char *last_cluster = NULL;
+	char *last_cluster2 = NULL;
 	uint32_t user_parent_id = 0;
 	uint32_t acct_parent_id = 0;
 
@@ -4702,18 +4839,21 @@ empty:
 		assoc->acct = xstrdup(row[ASSOC_REQ_ACCT]);
 		assoc->cluster = xstrdup(row[ASSOC_REQ_CLUSTER]);
 		
-		if(row[ASSOC_REQ_PARENT][0]) {
-			if(!last_acct_parent || !last_cluster 
+		if(!assoc_q->without_parent_info && row[ASSOC_REQ_PARENT][0]) {
+/* 			info("got %s?=%s and %s?=%s", */
+/* 			     row[ASSOC_REQ_PARENT], last_acct_parent, */
+/* 			     row[ASSOC_REQ_CLUSTER], last_cluster); */
+			if(!last_acct_parent || !last_cluster
 			   || strcmp(row[ASSOC_REQ_PARENT], last_acct_parent)
 			   || strcmp(row[ASSOC_REQ_CLUSTER], last_cluster)) {
-			
-			query = xstrdup_printf(
+				query = xstrdup_printf(
 					"select id from %s where user='' "
 					"and deleted = 0 and acct='%s' "
 					"and cluster='%s';", 
 					assoc_table, row[ASSOC_REQ_PARENT],
 					row[ASSOC_REQ_CLUSTER]);
-			
+				debug4("%d query\n%s", mysql_conn->conn, query);
+
 				if(!(result2 = mysql_db_query_ret(
 					     mysql_conn->acct_mysql_db,
 					     query, 1))) {
@@ -4738,14 +4878,15 @@ empty:
 		else
 			assoc->fairshare = 1;
 
-		if(!last_acct || !last_cluster 
-		   || strcmp(row[ASSOC_REQ_ACCT], last_acct)
-		   || strcmp(row[ASSOC_REQ_CLUSTER], last_cluster)) {
+		if((!last_acct || !last_cluster2 
+		    || strcmp(row[ASSOC_REQ_ACCT], last_acct)
+		    || strcmp(row[ASSOC_REQ_CLUSTER], last_cluster2))) {
 			query = xstrdup_printf(
-				"call get_parent_limits('%s', '%s', '%s');"
+				"call get_parent_limits('%s', '%s', '%s', %u);"
 				"select @par_id, @mj, @mnpj, @mwpj, @mcpj;", 
 				assoc_table, row[ASSOC_REQ_ACCT],
-				row[ASSOC_REQ_CLUSTER]);
+				row[ASSOC_REQ_CLUSTER],
+				assoc_q->without_parent_limits);
 			
 			if(!(result2 = mysql_db_query_ret(
 				     mysql_conn->acct_mysql_db, query, 1))) {
@@ -4756,29 +4897,29 @@ empty:
 			
 			row2 = mysql_fetch_row(result2);
 			user_parent_id = atoi(row2[ASSOC2_REQ_PARENT_ID]);
-			
-			if(row2[ASSOC2_REQ_MJ])
-				parent_mj = atoi(row2[ASSOC2_REQ_MJ]);
-			else
-				parent_mj = -1;
-			
-			if(row2[ASSOC2_REQ_MNPJ])
-				parent_mnpj = atoi(row2[ASSOC2_REQ_MNPJ]);
-			else
-				parent_mwpj = -1;
-			
-			if(row2[ASSOC2_REQ_MWPJ])
-				parent_mwpj = atoi(row2[ASSOC2_REQ_MWPJ]);
-			else
-				parent_mwpj = -1;
-			
-			if(row2[ASSOC2_REQ_MCPJ])
-				parent_mcpj = atoi(row2[ASSOC2_REQ_MCPJ]);
-			else 
-				parent_mcpj = -1;
-			
+			if(!assoc_q->without_parent_limits) {
+				if(row2[ASSOC2_REQ_MJ])
+					parent_mj = atoi(row2[ASSOC2_REQ_MJ]);
+				else
+					parent_mj = INFINITE;
+				
+				if(row2[ASSOC2_REQ_MNPJ])
+					parent_mnpj = atoi(row2[ASSOC2_REQ_MNPJ]);
+				else
+					parent_mwpj = INFINITE;
+				
+				if(row2[ASSOC2_REQ_MWPJ])
+					parent_mwpj = atoi(row2[ASSOC2_REQ_MWPJ]);
+				else
+					parent_mwpj = INFINITE;
+				
+				if(row2[ASSOC2_REQ_MCPJ])
+					parent_mcpj = atoi(row2[ASSOC2_REQ_MCPJ]);
+				else 
+					parent_mcpj = INFINITE;
+			}
 			last_acct = row[ASSOC_REQ_ACCT];
-			last_cluster = row[ASSOC_REQ_CLUSTER];
+			last_cluster2 = row[ASSOC_REQ_CLUSTER];
 			mysql_free_result(result2);
 		}
 		if(row[ASSOC_REQ_MJ])
@@ -4801,8 +4942,10 @@ empty:
 		else
 			assoc->max_cpu_secs_per_job = parent_mcpj;
 
-		if(assoc->parent_id != acct_parent_id)
+		/* don't do this unless this is an user association */
+		if(assoc->user && assoc->parent_id != acct_parent_id) 
 			assoc->parent_id = user_parent_id;
+
 		//info("parent id is %d", assoc->parent_id);
 		//log_assoc_rec(assoc);
 	}
@@ -5815,7 +5958,7 @@ extern int jobacct_storage_p_step_complete(mysql_conn_t *mysql_conn,
 		ave_cpu /= 100;
 	}
  
-	if(jobacct->min_cpu != (uint32_t)NO_VAL) {
+	if(jobacct->min_cpu != NO_VAL) {
 		ave_cpu2 = jobacct->min_cpu;
 		ave_cpu2 /= 100;
 	}
diff --git a/src/plugins/accounting_storage/mysql/mysql_rollup.c b/src/plugins/accounting_storage/mysql/mysql_rollup.c
index 6df63f9321cc850a1aacec24b5a5dc479ab81ecb..63e02bbceb173fc2c47ecc501a8042d819a1e75c 100644
--- a/src/plugins/accounting_storage/mysql/mysql_rollup.c
+++ b/src/plugins/accounting_storage/mysql/mysql_rollup.c
@@ -754,7 +754,7 @@ extern int mysql_monthly_rollup(mysql_conn_t *mysql_conn,
 	 * start. 
 	 */
 	query = xstrdup_printf("delete from %s where period_end < %d "
-			       "&& end != 0",
+			       "&& period_end != 0",
 			       event_table, start);
 	rc = mysql_db_query(mysql_conn->acct_mysql_db, query);
 	xfree(query);
diff --git a/src/plugins/accounting_storage/none/accounting_storage_none.c b/src/plugins/accounting_storage/none/accounting_storage_none.c
index 26a4c554d700cd548302bc18370be1d977fa21d2..33d85ef189803cdf46701156d962bb03fc1447b2 100644
--- a/src/plugins/accounting_storage/none/accounting_storage_none.c
+++ b/src/plugins/accounting_storage/none/accounting_storage_none.c
@@ -139,9 +139,9 @@ extern List acct_storage_p_modify_users(void *db_conn, uint32_t uid,
 	return SLURM_SUCCESS;
 }
 
-extern List acct_storage_p_modify_accts(void *db_conn, uint32_t uid,
-				       acct_account_cond_t *acct_q,
-				       acct_account_rec_t *acct)
+extern List acct_storage_p_modify_accounts(void *db_conn, uint32_t uid,
+					   acct_account_cond_t *acct_q,
+					   acct_account_rec_t *acct)
 {
 	return SLURM_SUCCESS;
 }
diff --git a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c
index b4a59425612e2399d99ba856702ca6749804b47c..70f748e66b0e62815fa6b8fd3d41d89307ae3c9d 100644
--- a/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c
+++ b/src/plugins/accounting_storage/pgsql/accounting_storage_pgsql.c
@@ -660,7 +660,8 @@ extern int init ( void )
 	char *location = NULL;
 #else
 	fatal("No Postgres database was found on the machine. "
-	      "Please check the configure log and run again.");	
+	      "Please check the config.log from the run of configure "
+	      "and run again.");	
 #endif
 	/* since this can be loaded from many different places
 	   only tell us once. */
@@ -793,9 +794,9 @@ extern List acct_storage_p_modify_users(PGconn *acct_pgsql_db, uint32_t uid,
 	return SLURM_SUCCESS;
 }
 
-extern List acct_storage_p_modify_accts(PGconn *acct_pgsql_db, uint32_t uid,
-				       acct_account_cond_t *acct_q,
-				       acct_account_rec_t *acct)
+extern List acct_storage_p_modify_accounts(PGconn *acct_pgsql_db, uint32_t uid,
+					   acct_account_cond_t *acct_q,
+					   acct_account_rec_t *acct)
 {
 	return SLURM_SUCCESS;
 }
@@ -1556,7 +1557,7 @@ extern List jobacct_storage_p_get_jobs_cond(PGconn *acct_pgsql_db,
 					    acct_job_cond_t *job_cond)
 {
 	List job_list = NULL;
-#ifdef HAVE_MYSQL
+#ifdef HAVE_PGSQL
 	if(!acct_pgsql_db || PQstatus(acct_pgsql_db) != CONNECTION_OK) {
 		if(!pgsql_get_db_connection(&acct_pgsql_db,
 					    pgsql_db_name, pgsql_db_info))
diff --git a/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c b/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c
index cbfba517fce818563e7e7f3beac6b7b935697690..9d602efaf27addcf29ad250f0fae5ee44e80b7d4 100644
--- a/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c
+++ b/src/plugins/accounting_storage/slurmdbd/accounting_storage_slurmdbd.c
@@ -298,9 +298,9 @@ extern List acct_storage_p_modify_users(void *db_conn, uint32_t uid,
 	return ret_list;
 }
 
-extern List acct_storage_p_modify_accts(void *db_conn, uint32_t uid,
-				       acct_account_cond_t *acct_q,
-				       acct_account_rec_t *acct)
+extern List acct_storage_p_modify_accounts(void *db_conn, uint32_t uid,
+					   acct_account_cond_t *acct_q,
+					   acct_account_rec_t *acct)
 {
 	slurmdbd_msg_t req, resp;
 	dbd_modify_msg_t get_msg;
diff --git a/src/plugins/auth/munge/auth_munge.c b/src/plugins/auth/munge/auth_munge.c
index c460bf6816e62cfb78a4f8f5a6c853768a3d703e..40329276514e60a8a53d4f5e5b41fcfded4d908a 100644
--- a/src/plugins/auth/munge/auth_munge.c
+++ b/src/plugins/auth/munge/auth_munge.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  *  auth_munge.c - SLURM auth implementation via Chris Dunlap's Munge
- *  $Id: auth_munge.c 14319 2008-06-23 21:28:52Z jette $
+ *  $Id: auth_munge.c 14360 2008-06-26 16:17:40Z da $
  *****************************************************************************
  *  Copyright (C) 2002-2007 The Regents of the University of California.
  *  Copyright (C) 2008 Lawrence Livermore National Security.
@@ -482,15 +482,29 @@ _decode_cred(slurm_auth_credential_t *c, char *socket)
 				munge_ctx_strerror(ctx));
 			goto again;
 		}
-
-		/*
-		 *  Print any valid credential data 
+#ifdef MULTIPLE_SLURMD
+		/* In multple slurmd mode this will happen all the
+		 * time since we are authenticating with the same
+		 * munged.
 		 */
-		error ("Munge decode failed: %s", munge_ctx_strerror(ctx));
-		_print_cred(ctx); 
-
-		plugin_errno = e + MUNGE_ERRNO_OFFSET;
-
+		if (e != EMUNGE_CRED_REPLAYED) {
+#endif
+			/*
+			 *  Print any valid credential data 
+			 */
+			error ("Munge decode failed: %s",
+			       munge_ctx_strerror(ctx));
+			_print_cred(ctx); 
+			
+			plugin_errno = e + MUNGE_ERRNO_OFFSET;
+#ifdef MULTIPLE_SLURMD
+		} else {
+			debug2("We had a replayed cred, "
+			       "but this is expected in multiple "
+			       "slurmd mode.");
+			e = 0;
+		}
+#endif
 		goto done;
 	}
 
diff --git a/src/plugins/jobcomp/mysql/jobcomp_mysql.c b/src/plugins/jobcomp/mysql/jobcomp_mysql.c
index 46a139d9bc9a4e0c644c3c3fc3ff06cb08ea3736..69f24292ca48c5b16dc9ec6b7b2b1ff2bb62fef6 100644
--- a/src/plugins/jobcomp/mysql/jobcomp_mysql.c
+++ b/src/plugins/jobcomp/mysql/jobcomp_mysql.c
@@ -227,7 +227,8 @@ extern int init ( void )
 	static int first = 1;
 #ifndef HAVE_MYSQL
 	fatal("No MySQL storage was found on the machine. "
-	      "Please check the configure ran and run again.");
+	      "Please check the config.log from the run of configure "
+	      "and run again.");	
 #endif
 	if(first) {
 		/* since this can be loaded from many different places
diff --git a/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c b/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c
index a56157c07e56762991d7f2bf1cf75a5daced4289..c9f9ad5b1fa57479f7dc59e38a1ad4eb4602d69e 100644
--- a/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c
+++ b/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c
@@ -250,7 +250,8 @@ extern int init ( void )
 	static int first = 1;
 #ifndef HAVE_PGSQL
 	fatal("No Postgresql storage was found on the machine. "
-	      "Please check the configure ran and run again.");
+	      "Please check the config.log from the run of configure "
+	      "and run again.");	
 #endif
 	if(first) {
 		/* since this can be loaded from many different places
diff --git a/src/plugins/mpi/mvapich/mvapich.c b/src/plugins/mpi/mvapich/mvapich.c
index 3182cb4a6cf32cb0d04e2a4e0134bed6105798e1..f817698b7e73b3f74833c13067e1b20c7a571d1b 100644
--- a/src/plugins/mpi/mvapich/mvapich.c
+++ b/src/plugins/mpi/mvapich/mvapich.c
@@ -58,6 +58,17 @@
 #include "src/common/net.h"
 #include "src/common/fd.h"
 
+/*
+ *  2008-07-03:
+ * 
+ *  This version of mvapich.c has been tested against the following
+ *   protocol versions:
+ *  
+ *   Version 8: (pmgr_collective): mvapich-1.0.1, mvapich-1.0
+ *   Version 5: mvapich-0.9.9 r1760, mvapich-0.9.7-mlx2.2.0
+ *   Version 3: mvapich-0.9.8
+ */
+
 /* NOTE: MVAPICH has changed protocols without changing version numbers.
  * This makes support of MVAPICH very difficult. 
  * Support for the following versions have been validated:
@@ -66,10 +77,11 @@
  * For MVAPICH 0.9.4 and 0.9.5, set MVAPICH_VERSION_REQUIRES_PIDS to 3
  *
  * See functions mvapich_requires_pids() below for other mvapich versions.
+ *
  */
 #define MVAPICH_VERSION_REQUIRES_PIDS 3
 
-#include "src/plugins/mpi/mvapich/mvapich.h"
+#include "mvapich.h"
 
 /* NOTE: AIX lacks timersub */
 /* Why are we using mvapich on AIX? */
@@ -85,13 +97,35 @@
 	} while (0)
 #endif
 
+
+/*
+ *  MVAPICH initialization data state codes
+ */
+enum mv_init_state
+{
+	MV_READ_VERSION,
+	MV_READ_RANK,
+	MV_READ_HOSTIDLEN,
+	MV_READ_HOSTID,
+	MV_READ_ADDRLEN,
+	MV_READ_ADDRS,
+	MV_READ_PIDLEN,
+	MV_READ_PID,
+	MV_INIT_DONE,
+};
+
 /*
- *  Information read from each MVAPICH process
+ *  Information cache for each MVAPICH process
  */
 struct mvapich_info
 {
-	int do_poll;          
+	int do_poll;              
+	enum mv_init_state state; /* Initialization state            */
+	int nread;                /* Amount of data read so far      */
+	int nwritten;             /* Amount of data written          */
+
 	int fd;             /* fd for socket connection to MPI task  */
+	int version;        /* Protocol version for this rank        */
 	int rank;           /* This process' MPI rank                */
 	int pidlen;         /* length of pid buffer                  */
 	char *pid;          /* This rank's local pid (V3 only)       */
@@ -114,6 +148,7 @@ struct mvapich_info
 /*  Globals for the mvapich thread.
  */
 int mvapich_verbose = 0;
+
 static time_t first_abort_time = 0;
 
 /*  Per-job step state information.  The MPI plugin may be called
@@ -125,6 +160,7 @@ struct mvapich_state {
 	struct mvapich_info **mvarray;
 	int fd;
 	int nprocs;
+	int nconnected;
 	int protocol_version;
 	int protocol_phase;
 	int connect_once;
@@ -136,6 +172,22 @@ struct mvapich_state {
 	mpi_plugin_client_info_t job[1];
 };
 
+/*
+ *  MVAPICH poll structure used by mvapich_poll_next, etc.
+ */
+struct mvapich_poll 
+{
+	mvapich_state_t      *st;
+	struct mvapich_info **mvmap;
+	struct pollfd        *fds;
+	int                   counter;
+	int                   nfds;
+};
+
+
+/*
+ *  mvapich debugging defines
+ */
 #define mvapich_debug(args...) \
 	do { \
 		if (mvapich_verbose) \
@@ -148,22 +200,14 @@ struct mvapich_state {
 			info ("mvapich: " args); \
 	} while (0);
 
-static struct mvapich_info * mvapich_info_create (void)
-{
-	struct mvapich_info *mvi = xmalloc (sizeof (*mvi));
-	memset (mvi, 0, sizeof (*mvi));
-	mvi->fd = -1;
-	mvi->rank = -1;
-	return (mvi);
-}
+#define mvapich_debug3(args...) \
+	do { \
+		if (mvapich_verbose > 2) \
+			info ("mvapich: " args); \
+	} while (0);
 
-static void mvapich_info_destroy (struct mvapich_info *mvi)
-{
-	xfree (mvi->addr);
-	xfree (mvi->pid);
-	xfree (mvi);
-	return;
-}
+
+static void do_timings (mvapich_state_t *st, const char *fmt, ...);
 
 static int mvapich_requires_pids (mvapich_state_t *st)
 {
@@ -174,8 +218,71 @@ static int mvapich_requires_pids (mvapich_state_t *st)
 	return (0);
 }
 
-static int mvapich_terminate_job (mvapich_state_t *st)
+/*
+ *  Return the number of ms left until the MVAPICH startup 
+ *   timeout expires.
+ */
+static int startup_timeout (mvapich_state_t *st)
+{
+	time_t now;
+	time_t remaining;
+
+	if (st->timeout <= 0)
+		return (-1);
+
+	now = time (NULL);
+
+	if (!st->start_time)
+		return (-1);
+
+	remaining = st->timeout - (now - st->start_time);
+
+	if (remaining >= 0)
+		return ((int) remaining * 1000);
+	else
+		return (0);
+}
+
+char * vmsg (const char *msg, va_list ap)
+{
+	int n = -1;
+	int size = BUFSIZ;
+	va_list vp;
+	char *p = xmalloc (size);
+
+	while (1) {
+		va_copy (vp, ap);
+		n = vsnprintf (p, size, msg, vp);
+		va_end (vp);
+
+		if (n > -1 && n < size)
+			return (p);
+
+		if (n > -1)
+			size = n + 1;
+		else if (n == -1)
+			size *= 2;
+
+		p = xrealloc (p, size);
+	}
+
+	return (p);
+}
+
+
+/*
+ *  Forcibly kill job (with optional error message).
+ */
+static int mvapich_terminate_job (mvapich_state_t *st, const char *msg, ...)
 {
+	if (msg) {
+		va_list ap;
+		va_start (ap, msg);
+		char *p = vmsg (msg, ap);
+		error ("mvapich: %s", p);
+		xfree (p);
+	}
+
 	slurm_kill_job_step (st->job->jobid, st->job->stepid, SIGKILL);
 	/* Give srun a chance to terminate job */
 	sleep (5);
@@ -184,7 +291,22 @@ static int mvapich_terminate_job (mvapich_state_t *st)
 	/* NORETURN */
 }
 
-static void report_absent_tasks (mvapich_state_t *st)
+static struct mvapich_info *mvapich_info_find (mvapich_state_t *st, int rank)
+{
+	int i;
+
+	for (i = 0; i < st->nprocs; i++) {
+		if (st->mvarray[i] && st->mvarray[i]->rank == rank)
+			return (st->mvarray[i]);
+	}
+	return (NULL);
+}
+
+/*
+ *  Issue a report of tasks/hosts that we may be waiting for.
+ *   by checking either mvi->fd < 0 || mvi->do_poll == 1.
+ */
+static void report_absent_tasks (mvapich_state_t *st, int check_do_poll)
 {
 	int i;
 	char buf[16];
@@ -193,7 +315,9 @@ static void report_absent_tasks (mvapich_state_t *st)
 	slurm_step_layout_t *sl = st->job->step_layout;
 
 	for (i = 0; i < st->nprocs; i++) {
-		if (st->mvarray[i]->fd < 0) {
+		struct mvapich_info *m = mvapich_info_find (st ,i);
+
+		if ((m == NULL) || (m->fd < 0) || (check_do_poll && m->do_poll)) {
 			const char *host = slurm_step_layout_host_name (sl, i);
 			sprintf (buf, "%d", i);
 			hostlist_push (tasks, buf);
@@ -209,7 +333,7 @@ static void report_absent_tasks (mvapich_state_t *st)
 		int nhosts = hostlist_count (hosts);
 		hostlist_ranged_string (tasks, 4096, r);
 		hostlist_ranged_string (hosts, 4096, h);
-		error ("mvapich: timeout: never heard from rank%s %s on host%s %s.\n", 
+		error ("mvapich: timeout: waiting on rank%s %s on host%s %s.\n", 
 				nranks > 1 ? "s" : "", r, 
 				nhosts > 1 ? "s" : "", h);
 	}
@@ -219,27 +343,153 @@ static void report_absent_tasks (mvapich_state_t *st)
 }
 
 
-static int startup_timeout (mvapich_state_t *st)
+static struct mvapich_info * mvapich_info_create (void)
 {
-	time_t now;
-	time_t remaining;
+	struct mvapich_info *mvi = xmalloc (sizeof (*mvi));
+	memset (mvi, 0, sizeof (*mvi));
+	mvi->fd = -1;
+	mvi->rank = -1;
+	mvi->state = MV_READ_VERSION;
+	mvi->nread = 0;
 
-	if (st->timeout <= 0)
-		return (-1);
+	return (mvi);
+}
 
-	now = time (NULL);
+static void mvapich_info_destroy (struct mvapich_info *mvi)
+{
+	xfree (mvi->addr);
+	xfree (mvi->pid);
+	xfree (mvi);
+	return;
+}
 
-	if (!st->start_time)
-		return (-1);
+/*
+ *  Reset an mvapich_poll object so it may be used again.
+ */
+static void mvapich_poll_reset (struct mvapich_poll *mp)
+{
+	int i;
+	mp->counter = 0;
+	mp->nfds = 0;
 
-	remaining = st->timeout - (now - st->start_time);
+	/*
+	 *  Reset mvapich_info do_poll attribute.
+	 */
+	for (i = 0; i < mp->st->nprocs; i++) 
+		mp->st->mvarray[i]->do_poll = 1;
+	return;
+}
 
-	if (remaining >= 0)
-		return ((int) remaining * 1000);
-	else
-		return (0);
+
+/*
+ *  Create an mvapich_poll object, used to poll all mvapich 
+ *   file descriptors for read/write activity
+ *
+ *  Resets do_poll for all mvapich_info objects in mvarray to 1.
+ *   (Thus, only one mvapich_poll should be in use at a time)
+ */
+static struct mvapich_poll * mvapich_poll_create (mvapich_state_t *st)
+{
+	struct mvapich_poll *mp = xmalloc (sizeof (*mp));
+
+	mp->mvmap   = xmalloc (st->nprocs * sizeof (struct mvapich_info *));
+	mp->fds     = xmalloc (st->nprocs * sizeof (struct pollfd));
+	mp->st = st;
+
+	mvapich_poll_reset (mp);
+
+	return (mp);
+}
+
+static void mvapich_poll_destroy (struct mvapich_poll *mp)
+{
+	xfree (mp->mvmap);
+	xfree (mp->fds);
+	xfree (mp);
+}
+
+/*
+ *  Poll for next available mvapich_info object with read/write activity
+ * 
+ *  Returns NULL when no more mvapich fds need to be polled.
+ *
+ *  The caller is responsible for updating mvi->do_poll to indicate
+ *    when a mvapich_info object's file descriptor no longer needs
+ *    to be polled for activity.
+ *
+ */
+static struct mvapich_info *
+mvapich_poll_next (struct mvapich_poll *mp, int do_read)
+{
+	int i, rc;
+	int event = do_read ? POLLIN : POLLOUT;
+	mvapich_state_t *st = mp->st;
+
+again:
+	/*
+	 *  If the loop counter is 0, then we need to reset data structures
+	 *    and poll again.
+	 */
+	if (mp->counter == 0) {
+		int j = 0;
+
+		memset (mp->fds, 0, sizeof (st->nprocs * sizeof (struct pollfd)));
+		memset (mp->mvmap, 0, sizeof (st->nprocs * sizeof (*mp->mvmap)));
+		mp->nfds = 0;
+
+		for (i = 0; i < st->nprocs; i++) {
+			struct mvapich_info *mvi = mp->st->mvarray [i];
+			if (mvi->do_poll) {
+				mp->mvmap[j] = mvi;
+				mp->fds[j].fd = mvi->fd;
+				mp->fds[j].events = event;
+				j++;
+				mp->nfds++;
+			}
+		}
+
+		/*
+		 *  If there are no more file descriptors to poll, then
+		 *   return NULL to indicate we're done.
+		 */
+		if (mp->nfds == 0)
+			return (NULL);
+
+		mvapich_debug3 ("mvapich_poll_next (nfds=%d, timeout=%d)\n", 
+				mp->nfds, startup_timeout (st));
+		if ((rc = poll (mp->fds, mp->nfds, startup_timeout (st))) < 0)
+			mvapich_terminate_job (st, "mvapich_poll_next: %m");
+		else if (rc == 0) {
+			/*
+			 *  If we timed out, then report all tasks that we were 
+			 *   still waiting for.
+			 */
+			report_absent_tasks (st, 1);
+			mvapich_terminate_job (st, NULL);
+		}
+	}
+
+	/*
+	 *  Loop through poll fds and return first mvapich_info object
+     *   we find that has the requested read/write activity. 
+	 *   When found, we update the loop counter, and return
+     *   the corresponding mvapich_info object.
+	 *
+	 */
+	for (i = mp->counter; i < mp->nfds; i++) {
+		if (mp->fds[i].revents == event) {
+			mp->counter = i+1;
+			return (mp->mvmap[i]);
+		}
+	}
+
+	mp->counter = 0;
+	goto again;
+
+	return (NULL);
 }
 
+
 static int mvapich_poll (mvapich_state_t *st, struct mvapich_info *mvi, 
 		                 int write) {
 	int rc = 0;
@@ -267,16 +517,70 @@ static int mvapich_poll (mvapich_state_t *st, struct mvapich_info *mvi,
 					mvi->rank, host);
 		} 
 		else {
-			report_absent_tasks (st);
+			report_absent_tasks (st, 0);
 		}
 
-		mvapich_terminate_job (st);
+		mvapich_terminate_job (st, NULL);
 		/* NORETURN */
 	}
 
 	return (rc);
 }
 
+static int mvapich_write (struct mvapich_info *mvi, void * buf, size_t len)
+{
+	size_t nleft;
+	ssize_t n;
+	unsigned char *p;
+
+	p = buf + mvi->nwritten;
+	nleft = len - mvi->nwritten;
+
+	n = write (mvi->fd, p, nleft);
+
+	if ((n < 0) && (errno != EAGAIN)) {
+		error ("mvapich: rank %d: write (%d/%ld): %m\n", mvi->rank, nleft, len);
+		return (-1);
+	}
+
+	if (n > 0)
+		mvi->nwritten += n;
+
+	if (mvi->nwritten == len) {
+		mvi->nwritten = 0;
+		mvi->do_poll = 0;
+	}
+
+	return (0);
+}
+
+static int mvapich_read (struct mvapich_info *mvi, void * buf, size_t len)
+{
+	size_t nleft;
+	ssize_t n;
+	unsigned char *p;
+
+	p = buf + mvi->nread;
+	nleft = len - mvi->nread;
+
+	n = read (mvi->fd, p, nleft);
+
+	if ((n < 0) && (errno != EAGAIN)) {
+		error ("mvapich: rank %d: read (%d/%ld): %m\n", mvi->rank, nleft, len);
+		return (-1);
+	}
+
+	if (n > 0)
+		mvi->nread += n;
+
+	if (mvi->nread == len) {
+		mvi->nread = 0;
+		mvi->do_poll = 0;
+	}
+
+	return (0);
+}
+
 static int mvapich_write_n (mvapich_state_t *st, struct mvapich_info *mvi,
 		                    void *buf, size_t len)
 {
@@ -303,14 +607,14 @@ static int mvapich_write_n (mvapich_state_t *st, struct mvapich_info *mvi,
 }
 
 static int mvapich_read_n (mvapich_state_t *st,  struct mvapich_info *mvi,
-						   void *buf, size_t len)
+		void *buf, size_t len)
 {
 	int nleft = len;
 	int n = 0;
 	unsigned char * p = buf;
 
 	while (nleft > 0) {
-		/* Poll for write-activity */
+		/* Poll for read-activity */
 		if (mvapich_poll (st, mvi, 0) < 0)
 			return (-1);
 
@@ -322,8 +626,8 @@ static int mvapich_read_n (mvapich_state_t *st,  struct mvapich_info *mvi,
 
 		if (n == 0) { /* unexpected EOF */
 			error ("mvapich: rank %d: "
-			       "Unexpected EOF (%dB left to read)", 
-			       mvi->rank, nleft);
+					"Unexpected EOF (%dB left to read)", 
+					mvi->rank, nleft);
 			return (-1);
 		}
 
@@ -350,122 +654,6 @@ static int mvapich_abort_sends_rank (mvapich_state_t *st)
 	return (0);
 }
 
-/*
- *  Create an mvapich_info object by reading information from
- *   file descriptor `fd'
- */
-static int mvapich_get_task_info (mvapich_state_t *st,
-				  struct mvapich_info *mvi)
-{
-	mvi->do_poll = 0;
-
-	if (mvapich_read_n (st, mvi, &mvi->addrlen, sizeof (int)) <= 0)
-		return error ("mvapich: Unable to read addrlen for rank %d: %m", 
-				mvi->rank);
-
-	mvi->addr = xmalloc (mvi->addrlen);
-
-	if (mvapich_read_n (st, mvi, mvi->addr, mvi->addrlen) <= 0)
-		return error ("mvapich: Unable to read addr info for rank %d: %m", 
-				mvi->rank);
-
-	if (!mvapich_requires_pids (st))
-		return (0);
-
-	if (mvapich_read_n (st, mvi, &mvi->pidlen, sizeof (int)) <= 0) {
-		return error ("mvapich: Unable to read pidlen for rank %d: %m", 
-				mvi->rank);
-	}
-
-	mvi->pid = xmalloc (mvi->pidlen);
-
-	if (mvapich_read_n (st, mvi, mvi->pid, mvi->pidlen) <= 0) {
-		return error ("mvapich: Unable to read pid for rank %d: %m", 
-				mvi->rank);
-	}
-
-	return (0);
-}
-
-static int mvapich_get_hostid (mvapich_state_t *st, struct mvapich_info *mvi)
-{
-	if (mvapich_read_n (st, mvi, &mvi->hostidlen, sizeof (int)) < 0) {
-		return error ("mvapich: Unable to read hostidlen for rank %d: %m",
-				mvi->rank);
-	}
-	if (mvi->hostidlen != sizeof (int)) {
-		return error ("mvapich: Unexpected size for hostidlen (%d)", 
-				mvi->hostidlen);
-	}
-	if (mvapich_read_n (st, mvi, &mvi->hostid, sizeof (int)) < 0) {
-		return error ("mvapich: unable to read hostid from rank %d", 
-				mvi->rank);
-	}
-
-	return (0);
-}
-
-static int mvapich_get_task_header (mvapich_state_t *st,
-				    int fd, int *version, int *rank)
-{
-	struct mvapich_info tmp[1] ;
-
-	fd_set_nonblocking (fd);
-
-	tmp->fd = fd;
-	tmp->rank = -1;
-
-	/*
-	 *  dual phase only sends version on first pass
-	 */
-	if (!mvapich_dual_phase (st) || st->protocol_phase == 0) {
-		if (mvapich_read_n (st, tmp, version, sizeof (int)) < 0) 
-			return error ("mvapich: Unable to read version from task: %m");
-	} 
-
-	if (mvapich_read_n (st, tmp, rank, sizeof (int)) < 0) 
-		return error ("mvapich: Unable to read task rank: %m");
-
-
-	if (mvapich_dual_phase (st) && st->protocol_phase > 0)
-		return (0);
-
-	if (st->protocol_version == -1)
-		st->protocol_version = *version;
-	else if (st->protocol_version != *version) {
-		return error ("mvapich: rank %d version %d != %d",
-			      *rank, *version, st->protocol_version);
-	}
-
-	return (0);
-
-}
-
-static int mvapich_handle_task (mvapich_state_t *st,
-				int fd, struct mvapich_info *mvi)
-{
-	mvi->fd = fd;
-
-	switch (st->protocol_version) {
-		case 1:
-		case 2:
-		case 3:
-			return mvapich_get_task_info (st, mvi);
-		case 5:
-		case 6:
-			if (st->protocol_phase == 0)
-				return mvapich_get_hostid (st, mvi);
-			else
-				return mvapich_get_task_info (st, mvi);
-		case 8:
-			return (0);
-		default:
-			return (error ("mvapich: Unsupported protocol version %d", 
-				       st->protocol_version));
-	}
-
-	return (0);
-}
 /*
  *  Broadcast addr information to all connected mvapich processes.
  *   The format of the information sent back to each process is:
@@ -487,6 +675,8 @@ static void mvapich_bcast_addrs (mvapich_state_t *st)
 	int i = 0;
 	int j = 0;
 
+	mvapich_debug2 ("Bcasting addrs to %d tasks", st->nprocs);
+
 	for (i = 0; i < st->nprocs; i++) {
 		m = st->mvarray[i];
 		/*
@@ -511,7 +701,10 @@ static void mvapich_bcast_addrs (mvapich_state_t *st)
 			out_addrs[st->nprocs + j] = 
 				(i == j) ? -1 : st->mvarray[j]->addr[i];
 
+		mvapich_debug3 ("writing addrs to task %d", i);
 		mvapich_write_n (st, m, out_addrs, out_addrs_len);
+		if (mvapich_verbose > 2)
+			do_timings (st, "Write addrs to task %d", i);
 
 		/*
 		 * Protocol version 3 requires pid list to be sent next
@@ -530,6 +723,8 @@ static void mvapich_bcast_addrs (mvapich_state_t *st)
 
 static void mvapich_bcast_hostids (mvapich_state_t *st)
 {
+	struct mvapich_poll *mp;
+	struct mvapich_info *mvi;
 	int *  hostids;
 	int    i   = 0;
 	size_t len = st->nprocs * sizeof (int);
@@ -539,22 +734,39 @@ static void mvapich_bcast_hostids (mvapich_state_t *st)
 	for (i = 0; i < st->nprocs; i++)
 		hostids [i] = st->mvarray[i]->hostid;
 
-	for (i = 0; i < st->nprocs; i++) {
-		struct mvapich_info *mvi = st->mvarray[i];
-		int co, rc;
-
-		if (mvapich_write_n (st, mvi, hostids, len) < 0)
-			error ("mvapich: write hostid rank %d: %m", mvi->rank);
+	/*
+	 *  Broadcast hostids
+	 */
+	mvapich_debug ("bcasting hostids\n");
+	mp = mvapich_poll_create (st);
+	while ((mvi = mvapich_poll_next (mp, 0))) {
+		if (mvapich_write (mvi, hostids, len) < 0) 
+			mvapich_terminate_job (st, "write hostid rank %d: %m", mvi->rank);
+	}
+	xfree (hostids);
 
-		if ((rc = mvapich_read_n (st, mvi, &co, sizeof (int))) <= 0) {
-			mvapich_debug2 ("reading connect once value rc=%d: %m\n", rc);
+	/*
+	 *  Read connect_once value from every rank
+	 *   Each rank will either close the connection (connect_once = 0)
+	 *    or send the connect_once value (presumed 1).
+	 */
+	mvapich_debug ("reading connect once value");
+	mvapich_poll_reset (mp);
+	while ((mvi = mvapich_poll_next (mp, 1))) {
+		int co = 1, rc;
+		mvapich_debug3 ("reading connect once value from rank %d fd=%d\n", 
+				mvi->rank, mvi->fd);
+		if ((rc = read (mvi->fd, &co, sizeof (int))) <= 0) {
+			mvapich_debug2 ("reading connect once value rc=%d: %m\n", rc);
 			close (mvi->fd);
+			mvi->fd = -1;
 			st->connect_once = 0;
-		} else
-			mvi->do_poll = 1;
+		}
+		mvi->do_poll = 0;
 	}
 
-	xfree (hostids);
+	mvapich_poll_destroy (mp);
+	return;
 }
 
 /* Write size bytes from buf into socket for rank */
@@ -574,29 +786,39 @@ static int mvapich_recv (mvapich_state_t *st, void* buf, int size, int rank)
 /* Scatter data in buf to ranks using chunks of size bytes */
 static int mvapich_scatterbcast (mvapich_state_t *st, void* buf, int size)
 {
-	int i, rc;
+	int rc;
 	int n = 0;
+	struct mvapich_poll *mp;
+	struct mvapich_info *mvi;
 
-	for (i = 0; i < st->nprocs; i++) {
-		if ((rc = mvapich_send (st, buf + i*size, size, i)) <= 0) 
-			return (-1);
+	mp = mvapich_poll_create (st);
+	while ((mvi = mvapich_poll_next (mp, 0))) {
+		if ((rc = mvapich_write (mvi, buf + (mvi->rank * size), size)) < 0)
+			break;
 		n += rc;
 	}
-	return (n);
+	mvapich_poll_destroy (mp);
+
+	return (rc < 0 ? rc : n);
 }
 
 /* Broadcast buf to each rank, which is size bytes big */
 static int mvapich_allgatherbcast (mvapich_state_t *st, void* buf, int size)
 {
-	int i, rc;
+	int rc = 0;
 	int n = 0;
+	struct mvapich_poll *mp;
+	struct mvapich_info *mvi;
 
-	for (i = 0; i < st->nprocs; i++) {
-		if ((rc = mvapich_send (st, buf, size, i)) <= 0)
-			return (-1);
+	mp = mvapich_poll_create (st);
+	while ((mvi = mvapich_poll_next (mp, 0))) {
+		if ((rc = mvapich_write (mvi, buf, size)) < 0)
+			break;
 		n += rc;
 	}
-	return (n);
+	mvapich_poll_destroy (mp);
+
+	return (rc < 0 ? rc : n);
 }
 
 /* Perform alltoall using data in buf with elements of size bytes */
@@ -610,16 +832,16 @@ static int mvapich_alltoallbcast (mvapich_state_t *st, void* buf, int size)
 	for (i = 0; i < st->nprocs; i++) {
 		for (src = 0; src < st->nprocs; src++) {
 			memcpy( pbuf + size*src,
-				buf + size*(src*st->nprocs + i),
-				size
-				);
+					buf + size*(src*st->nprocs + i),
+					size
+				  );
 		}
 		if ((rc = mvapich_send (st, pbuf, pbufsize, i)) <= 0)
 			goto out;
 		n += rc;
 	}
-	
-    out:
+
+out:
 	xfree(pbuf);
 	return (rc < 0 ? rc : n);
 }
@@ -628,9 +850,10 @@ static int recv_common_value (mvapich_state_t *st, int *valp, int rank)
 {
 	int val;
 	if (mvapich_recv (st, &val, sizeof (int), rank) <= 0) {
-		error ("mvapich: recv: rank %d: %m\n", rank);
+		error ("mvapich: recv_common_value: rank %d: %m\n", rank);
 		return (-1);
 	}
+	mvapich_debug3 ("recv_common_value (rank=%d, val=%d)\n", rank, *valp);
 
 	/*
 	 *  If value is uninitialized, set it to current value,
@@ -640,7 +863,7 @@ static int recv_common_value (mvapich_state_t *st, int *valp, int rank)
 		*valp = val;
 	else if (val != *valp) {
 		error ("mvapich: PMGR: unexpected value from rank %d: "
-		       "expected %d, recvd %d", rank, *valp, val);
+				"expected %d, recvd %d", rank, *valp, val);
 		return (-1);
 	}
 	return (0);
@@ -663,6 +886,7 @@ static int process_pmgr_bcast (mvapich_state_t *st, int *rootp, int *sizep,
 	 *  Recv data from root 
 	 */
 	*bufp = xmalloc (*sizep);
+	mvapich_debug3 ("PMGR_BCAST: recv from root\n");
 	if (mvapich_recv (st, *bufp, *sizep, rank) < 0) {
 		error ("mvapich: PMGR_BCAST: Failed to recv from root: %m");
 		return (-1);
@@ -682,7 +906,8 @@ static int process_pmgr_gather (mvapich_state_t *st, int *rootp,
 		return (-1);
 	if (*bufp == NULL)
 		*bufp = xmalloc (*sizep * st->nprocs);
-		
+
+	mvapich_debug3 ("PMGR_GATHER: recv from rank %d\n", rank);
 	if (mvapich_recv(st, (*bufp) + (*sizep)*rank, *sizep, rank) < 0) {
 		error ("mvapich: PMGR_/GATHER: rank %d: recv: %m", rank);
 		return (-1);
@@ -705,7 +930,7 @@ static int process_pmgr_scatter (mvapich_state_t *st, int *rootp,
 
 	if (*bufp == NULL)
 		*bufp = xmalloc (*sizep * st->nprocs);
-		
+	mvapich_debug3 ("PMGR_SCATTER: recv from rank %d", rank);	
 	if (mvapich_recv(st, *bufp, (*sizep) * st->nprocs, rank) < 0) {
 		error ("mvapich: PMGR_SCATTER: rank %d: recv: %m", rank);
 		return (-1);
@@ -723,6 +948,8 @@ static int process_pmgr_allgather (mvapich_state_t *st, int *sizep,
 		return (-1);
 	if (*bufp == NULL)
 		*bufp = xmalloc (*sizep * st->nprocs);
+
+	mvapich_debug3 ("PMGR_ALLGATHER: recv from rank %d\n", rank);
 	if (mvapich_recv (st, (*bufp) + *sizep*rank, *sizep, rank) < 0) {
 		error ("mvapich: PMGR_ALLGATHER: rank %d: %m", rank);
 		return (-1);
@@ -741,9 +968,10 @@ static int process_pmgr_alltoall (mvapich_state_t *st, int *sizep,
 
 	if (*bufp == NULL)
 		*bufp = xmalloc (*sizep * st->nprocs * st->nprocs);
+	mvapich_debug3 ("PMGR_ALLTOALL: recv from rank %d\n", rank);
 	if (mvapich_recv ( st, 
-	                   *bufp + (*sizep * st->nprocs)*rank,
-	                   *sizep * st->nprocs, rank ) < 0) {
+				*bufp + (*sizep * st->nprocs)*rank,
+				*sizep * st->nprocs, rank ) < 0) {
 		error ("mvapich: PMGR_ALLTOALL: recv: rank %d: %m", rank);
 		return (-1);
 	}
@@ -751,55 +979,29 @@ static int process_pmgr_alltoall (mvapich_state_t *st, int *sizep,
 	return (0);
 }
 
-/* 
- * This function carries out pmgr_collective operations to
- * bootstrap MPI.  These collective operations are modeled after
- * MPI collectives -- all tasks must call them in the same order
- * and with consistent parameters.
- *
- * Until a 'CLOSE' or 'ABORT' message is seen, we continuously loop
- * processing ops
- *   For each op, we read one packet from each rank (socket)
- *     A packet consists of an integer OP CODE, followed by variable
- *     length data depending on the operation
- *   After reading a packet from each rank, srun completes the
- *   operation by broadcasting data back to any destinations,
- *   depending on the operation being performed
- *
- * Note: Although there are op codes available for PMGR_OPEN and
- * PMGR_ABORT, neither is fully implemented and should not be used.
- */
-static int mvapich_processops (mvapich_state_t *st)
+
+static int mvapich_process_op (mvapich_state_t *st, 
+		struct mvapich_info *mvi, int *rootp, int *opcodep, 
+		void **bufp, int *sizep)
 {
-	/* Until a 'CLOSE' or 'ABORT' message is seen, we continuously 
-	 *  loop processing ops
-	 */
+	int rank, code, opcode = -1;
 	int exit = 0;
-	while (!exit) {
-	int opcode = -1;
-	int root   = -1;
-	int size   = -1;
-	void* buf = NULL;
 
-	mvapich_debug ("Processing PMGR opcodes");
+	// read in opcode
+	if (recv_common_value (st, opcodep, mvi->rank) < 0) {
+		error ("mvapich: rank %d: Failed to read opcode: %m", 
+				mvi->rank);
+		return (-1);
+	}
 
-	// for each process, read in one opcode and its associated data
-	int i;
-	for (i = 0; i < st->nprocs; i++) {
-		struct mvapich_info *mvi = st->mvarray [i];
+	opcode = *opcodep;
+	mvapich_debug3 ("rank %d: opcode=%d\n", mvi->rank, opcode);
 
-		// read in opcode
-		if (recv_common_value (st, &opcode, i) < 0) {
-			error ("mvapich: rank %d: Failed to read opcode: %m", 
-				mvi->rank);
-			return (-1);
-		}
+	// read in additional data depending on current opcode
 
-		// read in additional data depending on current opcode
-		int rank, code;
-		switch(opcode) {
+	switch (*opcodep) {
 		case 0: // PMGR_OPEN (followed by rank)
-			if (mvapich_recv (st, &rank, sizeof (int), i) <= 0) {
+			if (mvapich_recv (st, &rank, sizeof (int), mvi->rank) <= 0) {
 				error ("mvapich: PMGR_OPEN: recv: %m");
 				exit = 1;
 			}
@@ -808,53 +1010,57 @@ static int mvapich_processops (mvapich_state_t *st)
 			close(mvi->fd);
 			break;
 		case 2: // PMGR_ABORT (followed by exit code)
-			if (mvapich_recv (st, &code, sizeof (int), i) <= 0) {
+			if (mvapich_recv (st, &code, sizeof (int), mvi->rank) <= 0) {
 				error ("mvapich: PMGR_ABORT: recv: %m");
 			}
-			error("mvapich abort with code %d from rank %d", 
-				code, i);
+			error("mvapich abort with code %d from rank %d", code, mvi->rank);
 			break;
 		case 3: // PMGR_BARRIER (no data)
 			break;
 		case 4: // PMGR_BCAST
-			if (process_pmgr_bcast (st, &root, &size, &buf, i) < 0)
+			if (process_pmgr_bcast (st, rootp, sizep, bufp, mvi->rank) < 0)
 				return (-1);
 			break;
 		case 5: // PMGR_GATHER 
-			if (process_pmgr_gather (st, &root, &size, &buf, i) < 0)
+			if (process_pmgr_gather (st, rootp, sizep, bufp, mvi->rank) < 0)
 				return (-1);
 			break;
 		case 6: // PMGR_SCATTER 
-			if (process_pmgr_scatter (st, &root, 
-			                          &size, &buf, i) < 0)
+			if (process_pmgr_scatter (st, rootp, sizep, bufp, mvi->rank) < 0)
 				return (-1);
 			break;
 		case 7: // PMGR_ALLGATHER 
-			if (process_pmgr_allgather (st, &size, &buf, i) < 0)
+			if (process_pmgr_allgather (st, sizep, bufp, mvi->rank) < 0)
 				return (-1);
 			break;
 		case 8: // PMGR_ALLTOALL 
-			if (process_pmgr_alltoall (st, &size, &buf, i) < 0)
+			if (process_pmgr_alltoall (st, sizep, bufp, mvi->rank) < 0)
 				return (-1);
 			break;
 		default:
 			error("Unrecognized PMGR opcode: %d", opcode);
 			return (-1);
-		}
 	}
 
-	// Complete any operations
+	return (exit);
+}
+
+static int mvapich_complete_op (mvapich_state_t *st, int opcode, int root,
+		void *buf, int size)
+{
+	int rc = 0;
+
 	switch(opcode) {
 		case 0: // PMGR_OPEN
 			mvapich_debug ("Completed PMGR_OPEN");
 			break;
 		case 1: // PMGR_CLOSE
 			mvapich_debug ("Completed PMGR_CLOSE");
-			exit = 1;
+			rc = 1;
 			break;
 		case 2: // PMGR_ABORT
 			mvapich_debug ("Completed PMGR_ABORT");
-			exit = 1;
+			rc = 1;
 			break;
 		case 3: // PMGR_BARRIER (just echo the opcode back)
 			mvapich_debug ("Completing PMGR_BARRIER");
@@ -890,10 +1096,67 @@ static int mvapich_processops (mvapich_state_t *st)
 			error("Unrecognized PMGR opcode: %d", opcode);
 	}
 
-	xfree(buf);
-  } // while(!exit)
-  mvapich_debug ("Completed processing PMGR opcodes");
-  return (0);
+	return (rc);
+}
+
+static int mvapich_pmgr_loop (mvapich_state_t *st)
+{
+	int opcode = -1;
+	int root   = -1;
+	int size   = -1;
+	int done   = 0;
+	void * buf = NULL;
+
+	int completed = 0;
+	struct mvapich_info *mvi;
+	struct mvapich_poll *mp;
+
+	mvapich_debug ("Processing PMGR opcodes");
+
+	// for each process, read in one opcode and its associated data
+	mp = mvapich_poll_create (st);
+	while ((mvi = mvapich_poll_next (mp, 1))) {
+		done = mvapich_process_op (st, mvi, &root, &opcode, &buf, &size);
+		completed++;
+		mvi->do_poll = 0;
+	}
+	mvapich_poll_destroy (mp);
+
+	// Complete any operations
+	done = mvapich_complete_op (st, opcode, root, buf, size);
+
+	return (done);
+}
+
+
+/* 
+ * This function carries out pmgr_collective operations to
+ * bootstrap MPI.  These collective operations are modeled after
+ * MPI collectives -- all tasks must call them in the same order
+ * and with consistent parameters.
+ *
+ * Until a 'CLOSE' or 'ABORT' message is seen, we continuously loop
+ * processing ops
+ *   For each op, we read one packet from each rank (socket)
+ *     A packet consists of an integer OP CODE, followed by variable
+ *     length data depending on the operation
+ *   After reading a packet from each rank, srun completes the
+ *   operation by broadcasting data back to any destinations,
+ *   depending on the operation being performed
+ *
+ * Note: Although there are op codes available for PMGR_OPEN and
+ * PMGR_ABORT, neither is fully implemented and should not be used.
+ */
+static int mvapich_processops (mvapich_state_t *st)
+{
+	/* Until a 'CLOSE' or 'ABORT' message is seen, we continuously 
+	 *  loop processing ops
+	 */
+	mvapich_debug ("Initiated PMGR processing\n");
+	while (mvapich_pmgr_loop (st) != 1) {};
+	mvapich_debug ("Completed processing PMGR opcodes\n");
+
+	return (0);
 }
 
 static void mvapich_bcast (mvapich_state_t *st)
@@ -908,6 +1171,7 @@ static void mvapich_barrier (mvapich_state_t *st)
 {
 	int i;
 	struct mvapich_info *m;
+	struct mvapich_poll *mp;
 	/*
 	 *  Simple barrier to wait for qp's to come up. 
 	 *   Once all processes have written their rank over the socket,
@@ -915,23 +1179,15 @@ static void mvapich_barrier (mvapich_state_t *st)
 	 */
 
 	debug ("mvapich: starting barrier");
-
-	for (i = 0; i < st->nprocs; i++) {
-		int j;
-		m = st->mvarray[i];
-		if (mvapich_read_n (st, m, &j, sizeof (j)) == -1)
-			error("mvapich read on barrier");
-	}
+	mp = mvapich_poll_create (st);
+	while ((m = mvapich_poll_next (mp, 1)))
+		mvapich_read (m, &i, sizeof (i));
 
 	debug ("mvapich: completed barrier for all tasks");
 
-	for (i = 0; i < st->nprocs; i++) {
-		m = st->mvarray[i];
-		if (mvapich_write_n (st, m, &i, sizeof (i)) == -1)
-			error("mvapich: write on barrier: %m");
-		close (m->fd);
-		m->fd = -1;
-	}
+	mvapich_poll_reset (mp);
+	while ((m = mvapich_poll_next (mp, 0)))
+		mvapich_write (m, &m->rank, sizeof (m->rank));
 
 	return;
 }
@@ -1024,6 +1280,9 @@ static int mvapich_abort_accept (mvapich_state_t *st)
 	pfds->fd = st->fd;
 	pfds->events = POLLIN;
 
+	mvapich_debug3 ("Polling to accept MPI_ABORT timeout=%d", 
+			mvapich_abort_timeout ());
+
 	while ((rc = poll (pfds, 1, mvapich_abort_timeout ())) < 0) {
 		if (errno != EINTR)
 			return (-1);
@@ -1034,8 +1293,7 @@ static int mvapich_abort_accept (mvapich_state_t *st)
 	 *   waiting longer for remote IO, process exit, etc.
 	 */
 	if (rc == 0) {
-		error("Timeout waiting for all tasks after MVAPICH ABORT. Exiting.");
-		mvapich_terminate_job (st);
+		mvapich_terminate_job (st, "Timeout waiting for all tasks after ABORT.");
 		/* NORETURN */
 	}
 
@@ -1101,15 +1359,6 @@ static void mvapich_wait_for_abort(mvapich_state_t *st)
 	return; /* but not reached */
 }
 
-static void mvapich_mvarray_create (mvapich_state_t *st)
-{
-	int i;
-	st->mvarray = xmalloc (st->nprocs * sizeof (*(st->mvarray)));
-	for (i = 0; i < st->nprocs; i++) {
-		st->mvarray [i] = mvapich_info_create ();
-		st->mvarray [i]->rank = i;
-	}
-}
 
 static void mvapich_mvarray_destroy (mvapich_state_t *st)
 {
@@ -1119,203 +1368,571 @@ static void mvapich_mvarray_destroy (mvapich_state_t *st)
 	xfree (st->mvarray);
 }
 
-static int mvapich_rank_from_fd (mvapich_state_t *st, int fd)
+static void do_timings (mvapich_state_t *st, const char *fmt, ...)
 {
-	int rank = 0;
-	while (st->mvarray[rank]->fd != fd)
-		rank++;
-	return (rank);
-}
+	static int initialized = 0;
+	static struct timeval initv = { 0, 0 };
+	struct timeval tv;
+	struct timeval result;
+	char *msg;
+	va_list ap;
 
-static int mvapich_handle_connection (mvapich_state_t *st, int fd)
-{
-	int version, rank;
+	if (!st->do_timing)
+		return;
 
-	if (st->protocol_phase == 0 || !st->connect_once) {
-		if (mvapich_get_task_header (st, fd, &version, &rank) < 0)
-			return (-1);
 
-		if (rank > st->nprocs - 1) { 
-			return (error ("mvapich: task reported invalid rank (%d)", 
-					rank));
+	if (!initialized) {
+		if (gettimeofday (&initv, NULL) < 0)
+			error ("mvapich: do_timings(): gettimeofday(): %m\n");
+		initialized = 1;
+		return;
+	}
+
+	if (gettimeofday (&tv, NULL) < 0) {
+		error ("mvapich: do_timings(): gettimeofday(): %m\n");
+		return;
+	}
+
+	timersub (&tv, &initv, &result);
+
+	va_start (ap, fmt);
+	msg = vmsg (fmt, ap);
+	va_end (ap);
+
+	info ("mvapich: %s took %d.%03d seconds", msg, result.tv_sec,
+			result.tv_usec/1000);
+
+	xfree (msg);
+
+	return;
+}
+
+static int mvapich_read_item (struct mvapich_info *mvi, void *buf, size_t size)
+{
+	size_t nleft;
+	ssize_t n;
+	unsigned char *p;
 
-		st->mvarray[rank]->rank = rank;
+	p = buf + mvi->nread;
+	nleft = size - mvi->nread;
 
+	if ((n = read (mvi->fd, p, nleft)) < 0) {
+		if (errno == EAGAIN)
+			return (EAGAIN);
+		else {
+			error ("mvapich: %d: nread=%d, read (%d, %lx, size=%d, nleft=%d): %m", 
+					mvi->rank, mvi->nread, mvi->fd, buf, size, nleft);
+			return (-1);
 		}
-	} else {
-		rank = mvapich_rank_from_fd (st, fd);
 	}
 
-	if (mvapich_handle_task (st, fd, st->mvarray[rank]) < 0) 
-		return (-1);
+	mvi->nread += n;
+	if (mvi->nread == size) {
+		mvi->nread = 0;
+		mvi->state++;
+	} 
 
 	return (0);
 }
 
-static int poll_mvapich_fds (mvapich_state_t *st)
+/*
+ *  Process initial mvapich states to read items such as
+ *   version, rank, hostidlen, hostids... and so on.
+ * 
+ *  Current state is tracked int he mvapich_info object itself
+ *   and state transitions happen automatically in mvapich_read_item()
+ *   when the current item is completely read. Early exit from
+ *   the state processing may occur based on protocol version.
+ *   Similarly, some protocol version may enter state processing
+ *   at a different point.
+ * 
+ *  State processing is considered complete when state == MV_INIT_DONE.
+ *
+ */  
+static int mvapich_info_process_init (mvapich_state_t *st, 
+		                              struct mvapich_info *mvi)
 {
-	int i = 0;
-	int j = 0;
-	int rc;
-	int fd;
-	int nfds = 0;
-	struct pollfd *fds = xmalloc (st->nprocs * sizeof (struct pollfd));
+	int rc = 0;
 
-	for (i = 0; i < st->nprocs; i++) {
-		if (st->mvarray[i]->do_poll) {
-			fds[j].fd = st->mvarray[i]->fd;
-			fds[j].events = POLLIN;
-			j++;
-			nfds++;
+again:
+	switch (mvi->state) {
+	case MV_READ_VERSION:
+		mvapich_debug2 ("fd %d: reading mvapich version.", mvi->fd);
+		rc = mvapich_read_item (mvi, &mvi->version, sizeof (mvi->version));
+
+		if (mvi->state != MV_READ_RANK)
+			break;
+
+	case MV_READ_RANK:
+		if (st->protocol_version < 0)
+			st->protocol_version = mvi->version;
+
+		mvapich_debug2 ("fd %d: reading mvapich rank. version = %d", 
+				mvi->fd, mvi->version);
+
+		rc = mvapich_read_item (mvi, &mvi->rank, sizeof (int));
+
+		/*
+		 *  No hostids in protocol version 3.
+		 */
+		if (mvi->version == 3 && mvi->state == MV_READ_HOSTIDLEN) {
+			mvi->state = MV_READ_ADDRLEN;
+			goto again;
 		}
-	}
 
-	if ((rc = poll (fds, nfds, startup_timeout (st))) < 0) {
-		error ("mvapich: poll: %m");
-		xfree (fds);
-		return SLURM_ERROR;
+		if (mvi->version >= 8 || mvi->state != MV_READ_HOSTIDLEN)
+			break;
+
+	case MV_READ_HOSTIDLEN:
+		mvapich_debug2 ("rank %d: reading hostidlen.", mvi->rank);
+
+		mvi->hostidlen = 0;
+		rc = mvapich_read_item (mvi, &mvi->hostidlen, sizeof (mvi->hostidlen));
+
+		if (mvi->state != MV_READ_HOSTID)
+			break;
+
+	case MV_READ_HOSTID:
+		if (mvi->hostidlen != sizeof (int)) {
+			error ("mvapich: rank %d: unexpected hostidlen = %d\n",
+					mvi->rank, mvi->hostidlen); 
+			return (-1);
+		}
+		mvapich_debug2 ("rank %d: reading hostid. hostidlen = %d", 
+				mvi->rank, mvi->hostidlen);
+
+		rc = mvapich_read_item (mvi, &mvi->hostid, mvi->hostidlen);
+
+		if (mvi->state != MV_READ_ADDRLEN || mvi->version > 3)
+			break;
+	
+	case MV_READ_ADDRLEN:
+		mvapich_debug2 ("rank %d: read addrlen.", mvi->rank);
+
+		rc = mvapich_read_item (mvi, &mvi->addrlen, sizeof (mvi->addrlen));
+
+		if (mvi->state != MV_READ_ADDRS)
+			break;
+
+	case MV_READ_ADDRS:
+		mvapich_debug2 ("rank %d: read addr. addrlen = %d", 
+				mvi->rank, mvi->addrlen);
+
+		mvi->addr = xmalloc (mvi->addrlen);
+		rc = mvapich_read_item (mvi, mvi->addr, mvi->addrlen);
+
+		if (mvi->state != MV_READ_PIDLEN || !mvapich_requires_pids (st))
+			break;
+
+	case MV_READ_PIDLEN:
+		mvapich_debug2 ("rank %d: read pidlen", mvi->rank);
+
+		rc = mvapich_read_item (mvi, &mvi->pidlen, sizeof (int));
+
+		if (mvi->state != MV_READ_PID)
+			break;
+
+	case MV_READ_PID:
+		mvapich_debug2 ("rank %d: read pid: pidlen = %d", 
+				mvi->rank, mvi->pidlen);
+
+		mvi->pid = xmalloc (mvi->pidlen);
+
+		rc = mvapich_read_item (mvi, mvi->pid, mvi->pidlen);
+
+		break;
+
+	case MV_INIT_DONE:
+		break;
 	}
 
-	i = 0;
-	while (fds[i].revents != POLLIN)
-		i++;
+	/*
+	 *  If protocol doesn't read PIDs, we're done after ADDRs
+	 */
+	if (mvi->state == MV_READ_PIDLEN && !mvapich_requires_pids (st))
+		mvi->state = MV_INIT_DONE;
 
-	fd = fds[i].fd;
-	xfree (fds);
+	/*
+	 *  Protocol version 4,5,6: Done after reading HOSTID
+	 */
+	if (mvi->state == MV_READ_ADDRLEN && mvi->version >= 5) 
+		mvi->state = MV_INIT_DONE;
 
-	return (fd);
+	/*
+	 *  Protocol version 8: Done after reading RANK
+	 */
+	if (mvi->state == MV_READ_HOSTIDLEN && mvi->version == 8) 
+		mvi->state = MV_INIT_DONE;
+
+	return (rc);
 }
-static int mvapich_get_next_connection (mvapich_state_t *st)
+
+
+/*
+ *  Accept as many new connections as possible and place them on
+ *   the next available slot in the mvarray.
+ */
+static int mvapich_accept_new (mvapich_state_t *st)
 {
 	slurm_addr addr;
 	int fd;
-	int rc;
-	struct mvapich_info tmp[1];
 
-	if (st->connect_once && st->protocol_phase > 0) {
-		return (poll_mvapich_fds (st));
-	} 
-		
-	tmp->fd = st->fd;
-	tmp->rank = -1;
-	if ((rc = mvapich_poll (st, tmp, 0)) == 0)
-		report_absent_tasks (st);
-	else if (rc < 0) {
-		error ("mvapich: poll for accept: %m");
-		return (-1);
-	}
-		
+	/*
+	 *  Accept as many new connections as possible
+	 */
+	while (1) {
+		if ( ((fd = slurm_accept_msg_conn (st->fd, &addr)) < 0) 
+		   && errno == EAGAIN) {
+			mvapich_debug2 ("mvapich: accept new: %m");
+			return (0);
+		}
+		else if (fd < 0) {
+			error ("mvapich: accept: %m");
+			return (-1);
+		}
 
-	if ((fd = slurm_accept_msg_conn (st->fd, &addr)) < 0) {
-		error ("mvapich: accept: %m");
-		return (-1);
+		if (st->nconnected == 0 && st->protocol_phase == 0) {
+			mvapich_debug ("first task connected");
+			do_timings (st, NULL);
+			/*
+			 *  Officially start timeout timer now.
+			 */
+			st->start_time = time (NULL);
+		}
+
+		fd_set_nonblocking (fd);
+
+		st->mvarray[st->nconnected] = mvapich_info_create ();
+		st->mvarray[st->nconnected]->fd = fd;
+		st->nconnected++;
+
+		mvapich_debug3 ("Got connection %d: fd=%d\n", st->nconnected, fd);
 	}
-	mvapich_debug2 ("accept() = %d", fd);
 
-	return (fd);
+	return (0);
 }
 
-static void do_timings (mvapich_state_t *st)
+/*
+ *  Accept new connections on st->fd and process them with the
+ *   function [fn].  The poll loop preferentially handles incoming 
+ *   connections to avoid exceeding the socket listen queue, which can 
+ *   be quite likely when launching very large jobs. 
+ * 
+ *  When there are no connections waiting, and existing connections register 
+ *   read activity, these connections are processed using [fn], until
+ *   such time as the mvapich_info state == MV_INIT_DONE.
+ *
+ */
+static int 
+mvapich_initialize_connections (mvapich_state_t *st, 
+		int (fn) (mvapich_state_t *, struct mvapich_info *) )
 {
-	static int initialized = 0;
-	static struct timeval initv = { 0, 0 };
-	struct timeval tv;
-	struct timeval result;
+	int i, j;
+	int nfds;
+	int ncompleted;
+	int rc = 0;
+	int printonce = 0;
+	struct mvapich_info **mvmap;
+	struct pollfd *fds;
+	
+	fds = xmalloc ((st->nprocs+1) * sizeof (struct pollfd));
+	mvmap = xmalloc (st->nprocs * sizeof (struct mvapich_info *));
+	st->nconnected = 0;
 
-	if (!st->do_timing)
-		return;
+	while (1) {
 
-	if (!initialized) {
-		if (gettimeofday (&initv, NULL) < 0)
-			error ("mvapich: do_timings(): gettimeofday(): %m\n");
-		initialized = 1;
-		return;
+		memset (fds, 0, sizeof (struct pollfd) * (st->nprocs + 1));
+		memset (mvmap, 0, sizeof (struct mvapich_info *) * st->nprocs);
+
+		/*
+		 *  Listen socket
+		 */
+		fds[0].fd = st->fd;
+		fds[0].events = POLLIN;
+
+		j = 1;
+		nfds = 1;
+		ncompleted = 0;
+
+		if (st->nconnected < st->nprocs)
+			mvapich_debug2 ("Waiting for connection %d/%d\n", 
+					st->nconnected + 1, st->nprocs);
+
+		for (i = 0; i < st->nconnected; i++) {
+			struct mvapich_info *m = st->mvarray[i];
+
+			if (m->fd >= 0 && m->state < MV_INIT_DONE) {
+				mvmap[j-1] = m;
+				fds[j].fd = m->fd;
+				fds[j].events = POLLIN;
+				j++;
+				nfds++;
+			}
+			else if (m->fd > 0 && m->state == MV_INIT_DONE)
+				ncompleted++;
+		}
+
+		if (st->nconnected == st->nprocs && !printonce) {
+			mvapich_debug ("Got %d connections.\n", st->nprocs);
+			do_timings (st, "Accept %d connection%s%s", 
+					st->nprocs, st->nprocs == 1 ? "" : "s",
+					st->protocol_phase ? " (phase 2)" : "");
+			printonce = 1;
+		}
+
+		if (ncompleted == st->nprocs) {
+			do_timings (st, "Read info for %d task%s%s",
+					st->nprocs, st->nprocs == 1 ? "" : "s",
+					st->protocol_phase ? " (phase 2)" : "");
+			break; /* All done. */
+		}
+
+		mvapich_debug3 ("do_poll (nfds=%d)\n", nfds);
+
+		if ((rc = poll (fds, nfds, startup_timeout (st))) < 0) {
+			error ("mvapich: poll: %m");
+			break;
+		}
+		else if (rc == 0) {
+			report_absent_tasks (st, 1);
+			mvapich_terminate_job (st, NULL);
+		}
+
+		mvapich_debug3 ("poll (nfds=%d) = %d\n", nfds, rc);
+
+		/*
+		 *  Preferentially accept new connections.
+		 */
+		if (fds[0].revents == POLLIN) {
+			if ((rc = mvapich_accept_new (st)) < 0) 
+				break;
+			continue;
+		}
+
+		/*
+		 *  If there are no pending connections, handle read
+		 *   activity with passed in function [fn].
+		 */
+		for (i = 0; i < st->nconnected; i++) {
+			if (fds[i+1].revents == POLLIN) {
+				if ((rc = (*fn) (st, mvmap[i])) < 0) 
+					goto out;
+			}
+		}
 	}
 
-	if (gettimeofday (&tv, NULL) < 0) {
-		error ("mvapich: do_timings(): gettimeofday(): %m\n");
-		return;
+  out:
+	xfree (fds);
+	xfree (mvmap);
+	return (rc);
+}
+
+
+static int mvapich_phase_two (mvapich_state_t *st)
+{
+	struct mvapich_poll *mp;
+	struct mvapich_info *mvi;
+	int i;
+
+	/*
+	 *  For phase 2, start reading addrlen for all tasks:
+	 */
+	for (i = 0; i < st->nprocs; i++) 
+		st->mvarray[i]->state = MV_READ_ADDRLEN;
+
+	mvapich_debug ("Reading addrs from all tasks");
+	mp = mvapich_poll_create (st);
+	while ((mvi = mvapich_poll_next (mp, 1))) {
+
+		mvapich_info_process_init (st, mvi);
+
+		if (mvi->state == MV_INIT_DONE) 
+			mvi->do_poll = 0;
 	}
+	mvapich_poll_destroy (mp);
 
-	timersub (&tv, &initv, &result);
+	do_timings (st, "Reading addrs from %d tasks", st->nprocs);
 
-	info ("mvapich: Intialization took %d.%03d seconds", result.tv_sec,
-			result.tv_usec/1000);
+	mvapich_bcast_addrs (st);
 
-	return;
+	do_timings (st, "Bcast addrs to %d tasks", st->nprocs);
+
+	return (0);
 }
 
-static void *mvapich_thr(void *arg)
+static int read_phase2_header (mvapich_state_t *st, struct mvapich_info *mvi)
 {
-	mvapich_state_t *st = arg;
-	int i = 0;
-	int first = 1;
+	int rc;
 
-	debug ("mvapich-0.9.x/gen2: thread started: %ld", pthread_self ());
+	/*
+	 *  Phase 2 header is just our rank, so we know who the
+	 *   new connection is coming from.
+	 */
+	if ((rc = mvapich_read (mvi, &mvi->rank, sizeof (mvi->rank))) < 0)
+		error ("mvapich_read: %m");
+	/*
+	 *  mvapich_read resets do_poll if we're done reading. 
+	 *   Use this to set our state to MV_INIT_DONE so we don't continue
+	 *   to poll on this fd.
+	 */
+	if (mvi->do_poll == 0)
+		mvi->state = MV_INIT_DONE;
 
-	mvapich_mvarray_create (st);
+	return (rc);
+}
 
-again:
-	i = 0;
-	while (i < st->nprocs) {
-		int fd;
-		
-		mvapich_debug ("Waiting to accept remote connection %d of %d\n", 
-				i, st->nprocs);
-
-		if ((fd = mvapich_get_next_connection (st)) < 0) {
-			error ("mvapich: accept: %m");
-			goto fail;
-		}
+static int mvapich_handle_phase_two (mvapich_state_t *st)
+{
+	mvapich_debug ("protocol phase 0 complete. beginning phase 2.\n");
 
-		if (first) {
-			mvapich_debug ("first task checked in");
-			do_timings (st);
-			/*
-			 *  Officially start timeout timer now.
-			 */
-			st->start_time = time(NULL);
-			first = 0;
+	st->protocol_phase = 1;
+
+	/*
+	 *  Phase 2 is either in "connect_once" mode, where we reuse
+	 *   the existing connection (easy), or we have to handle the
+	 *   remote tasks reconnecting and re-sending their ranks
+	 *   before restarting the protocol. Since we don't know which
+	 *   connection is from which rank, we have to use a temporary
+	 *   mvapich_info array until all ranks have been read.
+	 */
+	if (!st->connect_once)  {
+		struct mvapich_info **mvarray = st->mvarray;
+		int i;
+
+		mvapich_debug ("Waiting for %d ranks to reconnect", st->nprocs);
+
+		/*
+		 *  Create temporary mvarray to handle incoming connections
+		 */
+		st->mvarray = xmalloc (st->nprocs * sizeof (struct mvapich_info *));
+
+		/*
+		 *  Accept all incoming connections and read the header (rank).
+		 */
+		if (mvapich_initialize_connections (st, read_phase2_header) < 0) 
+			mvapich_terminate_job (st, "Failed to initialize phase 2");
+
+		do_timings (st, "Phase 2 reconnect");
+
+		/*
+		 *  Now reassign mvi->fds in the real mvarray, and copy
+		 *   this back to st->mvarray.
+		 */
+		for (i = 0; i < st->nprocs; i++) {
+			struct mvapich_info *mvi = st->mvarray[i];
+			mvarray[mvi->rank]->fd = mvi->fd;
 		}
 
-		if (mvapich_handle_connection (st, fd) < 0) 
+		xfree (st->mvarray);
+		st->mvarray = mvarray;
+	}
+
+	/*
+	 *  Finish processing phase two.
+	 */
+	mvapich_phase_two (st);
+
+	return (0);
+}
+
+/*
+ *  Intialize all NPROCS connections
+ */
+static void mvapich_connection_init (mvapich_state_t *st)
+{
+	struct mvapich_info **mva;
+	int i;
+
+	st->mvarray = xmalloc (st->nprocs * sizeof (*(st->mvarray)));
+
+	/*
+	 *  Get initial connections and read task header information:
+	 */
+	if (mvapich_initialize_connections (st, mvapich_info_process_init) < 0) 
+		goto fail;
+
+	/*
+	 *  Sort mvarray in rank order. The rest of the startup code 
+	 *   expects this.
+	 */
+	mva = xmalloc (st->nprocs * sizeof (*mva));
+	for (i = 0; i < st->nprocs; i++) {
+		if ((mva[i] = mvapich_info_find (st, i)) == NULL) {
+			error ("mvapich: failed to find rank %d!", i);
 			goto fail;
+		}
+	}
+	xfree (st->mvarray);
+	st->mvarray = mva;
 
-		i++;
+	return;
+
+fail:
+	mvapich_terminate_job (st, "Fatal error. Killing job");
+	return;
+}
+
+/*
+ *  Close all fds in mvarray
+ */
+static void mvapich_close_fds (mvapich_state_t *st)
+{
+	int i;
+	for (i = 0; i < st->nprocs; i++) {
+		struct mvapich_info *mvi = st->mvarray[i];
+		close (mvi->fd);
+		mvi->fd = -1;
 	}
+}
+
+/*
+ *  This separate mvapich thread handles the MVAPICH startup 
+ *   protocol (tries to handle the many versions of it...).
+ */
+static void *mvapich_thr(void *arg)
+{
+	mvapich_state_t *st = arg;
 
+	/*
+	 *  Accept and initialize all remote task connections:
+	 */
+	mvapich_connection_init (st);
+
+	/*
+	 *  Process subsequent phases of various protocol versions.
+	 */
 	if (st->protocol_version == 8) {
-		if (mvapich_processops(st) < 0)
-			goto fail;
-	} else {
+		if (mvapich_processops (st) < 0) 
+			mvapich_terminate_job (st, "mvapich_processops failed.");
+	}
+	else {
 		mvapich_debug ("bcasting mvapich info to %d tasks", st->nprocs);
 		mvapich_bcast (st);
+		do_timings (st,"Bcasting mvapich info to %d tasks", st->nprocs);
 
 		if (mvapich_dual_phase (st) && st->protocol_phase == 0) {
-			mvapich_debug2 ("protocol phase 0 complete\n");
-			st->protocol_phase = 1;
-			goto again;
+			if (mvapich_handle_phase_two (st) < 0)
+				mvapich_terminate_job (st, "Phase 2 failed.");
 		}
 
+		do_timings (st, "Phase 2");
+
 		mvapich_debug ("calling mvapich_barrier");
 		mvapich_barrier (st);
 		mvapich_debug ("all tasks have checked in");
+		mvapich_close_fds (st);
 	}
 
-	do_timings (st);
+	do_timings (st, "MVAPICH initialization");
 
 	mvapich_wait_for_abort (st);
 
 	mvapich_mvarray_destroy (st);
 
 	return (NULL);
-
-fail:
-	error ("mvapich: fatal error, killing job");
-	mvapich_terminate_job (st);
-	return (void *)0;
 }
 
+
 static int process_environment (mvapich_state_t *st)
 {
 	char *val;
@@ -1368,13 +1985,65 @@ static void mvapich_state_destroy(mvapich_state_t *st)
 
 /*
  *  Create a unique MPIRUN_ID for jobid/stepid pairs.
- *  Combine the least significant bits of the jobid and stepid
+ *   Combine the least significant bits of the jobid and stepid
+ *
+ *  The MPIRUN_ID is used by MVAPICH to create shmem files in /tmp,
+ *   so we have to make sure multiple jobs and job steps on the
+ *   same node have different MPIRUN_IDs.
  */
 int mpirun_id_create(const mpi_plugin_client_info_t *job)
 {
 	return (int) ((job->jobid << 16) | (job->stepid & 0xffff));
 }
 
+/*
+ * Returns the port number in host byte order.
+ */
+static short _sock_bind_wild(int sockfd)
+{
+	socklen_t len;
+	struct sockaddr_in sin;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = htonl(INADDR_ANY);
+	sin.sin_port = htons(0);    /* bind ephemeral port */
+
+	if (bind(sockfd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
+		return (-1);
+	len = sizeof(sin);
+	if (getsockname(sockfd, (struct sockaddr *) &sin, &len) < 0)
+		return (-1);
+	return ntohs(sin.sin_port);
+}
+
+
+int do_listen (int *fd, short *port)
+{
+	int rc, val;
+
+	if ((*fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+		return -1;
+
+	val = 1;
+	rc = setsockopt(*fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int));
+	if (rc > 0)
+		goto cleanup;
+
+	*port = _sock_bind_wild(*fd);
+	rc = listen(*fd, 2048);
+
+	if (rc < 0)
+		goto cleanup;
+
+	return 1;
+
+cleanup:
+	close(*fd);
+	return -1;
+
+}
+
 extern mvapich_state_t *mvapich_thr_create(const mpi_plugin_client_info_t *job,
 					   char ***env)
 {
@@ -1388,7 +2057,7 @@ extern mvapich_state_t *mvapich_thr_create(const mpi_plugin_client_info_t *job,
 		mvapich_state_destroy(st);
 		return NULL;
 	}
-	if (net_stream_listen(&st->fd, &port) < 0) {
+	if (do_listen (&st->fd, &port) < 0) {
 		error ("Unable to create ib listen port: %m");
 		mvapich_state_destroy(st);
 		return NULL;
@@ -1419,7 +2088,7 @@ extern mvapich_state_t *mvapich_thr_create(const mpi_plugin_client_info_t *job,
 		env_array_overwrite_fmt(env, "MPIRUN_CONNECT_ONCE", "1");
 	}
 
-	verbose ("mvapich-0.9.[45] master listening on port %hu", port);
+	verbose ("mvapich-0.9.x,1.0.x master listening on port %hu", port);
 
 	return st;
 }
diff --git a/src/plugins/sched/wiki2/get_nodes.c b/src/plugins/sched/wiki2/get_nodes.c
index 58f3a00acc6da7abeea3bf168662f6aada4fddd1..af8263ded38ecbc44bf0d4f1c6e796e6ca85b152 100644
--- a/src/plugins/sched/wiki2/get_nodes.c
+++ b/src/plugins/sched/wiki2/get_nodes.c
@@ -375,8 +375,11 @@ static char *	_get_node_state(struct node_record *node_ptr)
 	}
 
 	if ((state & NODE_STATE_DRAIN)
-	||  (state & NODE_STATE_FAIL))
+	||  (state & NODE_STATE_FAIL)) {
+		if (base_state == NODE_STATE_IDLE)
+			return "Drained";
 		return "Draining";
+	}
 	if (state & NODE_STATE_COMPLETING)
 		return "Busy";
 
diff --git a/src/plugins/select/bluegene/block_allocator/block_allocator.c b/src/plugins/select/bluegene/block_allocator/block_allocator.c
index 216bb3814b1cd3773652d670e400309537451e06..b8780f96fe850aa78c24f8cd4f22aae4f067d0db 100644
--- a/src/plugins/select/bluegene/block_allocator/block_allocator.c
+++ b/src/plugins/select/bluegene/block_allocator/block_allocator.c
@@ -1,7 +1,7 @@
 /*****************************************************************************\
  *  block_allocator.c - Assorted functions for layout of bglblocks, 
  *	 wiring, mapping for smap, etc.
- *  $Id: block_allocator.c 14322 2008-06-23 22:01:33Z da $
+ *  $Id: block_allocator.c 14348 2008-06-25 19:05:31Z da $
  *****************************************************************************
  *  Copyright (C) 2004 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -1571,9 +1571,6 @@ extern int removable_set_bps(char *bps)
 extern int reset_all_removed_bps()
 {
 	int x;
-#ifdef HAVE_BG
-	int y,z;
-#endif
 
 	for (x = 0; x < DIM_SIZE[X]; x++) {
 #ifdef HAVE_BG
diff --git a/src/plugins/switch/federation/federation.c b/src/plugins/switch/federation/federation.c
index 3010298bfb87da5c4998929279a4d842d59c817e..6e20a93f1eb15c52728ca477986b6f67bffa26e9 100644
--- a/src/plugins/switch/federation/federation.c
+++ b/src/plugins/switch/federation/federation.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  **  federation.c - Library routines for initiating jobs on IBM Federation
- **  $Id: federation.c 13702 2008-03-22 00:13:35Z jette $
+ **  $Id: federation.c 14365 2008-06-26 19:17:00Z jette $
  *****************************************************************************
  *  Copyright (C) 2004 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -2550,9 +2550,15 @@ _unpack_libstate(fed_libstate_t *lp, Buf buffer)
 	
 	safe_unpack32(&lp->magic, buffer);
 	safe_unpack32(&node_count, buffer);
-	for(i = 0; i < node_count; i++)
-		(void)_unpack_nodeinfo(NULL, buffer, false);
-	assert(lp->node_count == node_count);
+	for(i = 0; i < node_count; i++) {
+		if (_unpack_nodeinfo(NULL, buffer, false) != SLURM_SUCCESS)
+			goto unpack_error;
+	}
+	if(lp->node_count != node_count) {
+		error("Failed to recover switch state of all nodes (%d of %u)",
+		      lp->node_count, node_count);
+		return SLURM_ERROR;
+	}
 	safe_unpack16(&lp->key_index, buffer);
 	
 	return SLURM_SUCCESS;
diff --git a/src/plugins/task/affinity/dist_tasks.c b/src/plugins/task/affinity/dist_tasks.c
index 9a725dc1afcfde72ffe89d2a1dea3a7e9f0600d0..357fbc5e09a281e83f4957953b125614b09a95f0 100644
--- a/src/plugins/task/affinity/dist_tasks.c
+++ b/src/plugins/task/affinity/dist_tasks.c
@@ -32,6 +32,7 @@
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 \*****************************************************************************/
 
+#include <limits.h>       /* INT_MAX */
 #include "src/plugins/task/affinity/dist_tasks.h"
 
 static slurm_lllp_ctx_t *lllp_ctx = NULL;	/* binding context */
diff --git a/src/sacct/options.c b/src/sacct/options.c
index 432c3f86014f2c2cb9a32e5cb0129a6f815603fd..4f0a729906c1b8dcb5180bde9fe200d9fa0a45f3 100644
--- a/src/sacct/options.c
+++ b/src/sacct/options.c
@@ -1141,6 +1141,7 @@ void do_list(void)
 				}
 				if(step->end == 0)
 					step->end = job->end;
+				step->account = job->account;
 				print_fields(JOBSTEP, step);
 			} 
 			list_iterator_destroy(itr_step);
diff --git a/src/sacct/print.c b/src/sacct/print.c
index 91c1231b18a2028a5ce4a09f22c55e8878eb188f..d1ff6e5f8b8b884a7ff41ebbc6307d6e2e454f4d 100644
--- a/src/sacct/print.c
+++ b/src/sacct/print.c
@@ -1070,6 +1070,7 @@ void print_cputime(type_t type, void *object)
 void print_account(type_t type, void *object)
 {
 	jobacct_job_rec_t *job = (jobacct_job_rec_t *)object;
+	jobacct_step_rec_t *step = (jobacct_step_rec_t *)object;
 
 	switch(type) {
 	case HEADLINE:
@@ -1087,7 +1088,13 @@ void print_account(type_t type, void *object)
 			printf("%-13.13s...", job->account);
 		break;
 	case JOBSTEP:
-		printf("%-16s", " ");
+		if(!step->account)
+			printf("%-16s", "unknown");
+		else if(strlen(step->account)<17)
+			printf("%-16s", step->account);
+		else
+			printf("%-13.13s...", step->account);
+		break;
 	default:
 		printf("%-16s", "n/a");
 		break;
diff --git a/src/sacctmgr/Makefile.am b/src/sacctmgr/Makefile.am
index c495e0e102fee1459c4ac06cc09f50d237468c98..8ff241fbb587069055029d643cf27ce76280be55 100644
--- a/src/sacctmgr/Makefile.am
+++ b/src/sacctmgr/Makefile.am
@@ -11,6 +11,7 @@ sacctmgr_SOURCES =	\
 	association_functions.c	\
 	cluster_functions.c	\
 	common.c                \
+	file_functions.c	\
 	sacctmgr.c sacctmgr.h	\
 	user_functions.c	
 
diff --git a/src/sacctmgr/Makefile.in b/src/sacctmgr/Makefile.in
index 072c2a165387ce8d47bde9c2bc92bd1bf8b14345..1a61db6f7dde9714520190e2acc11553ebc8833d 100644
--- a/src/sacctmgr/Makefile.in
+++ b/src/sacctmgr/Makefile.in
@@ -72,7 +72,8 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
 am_sacctmgr_OBJECTS = account_functions.$(OBJEXT) \
 	association_functions.$(OBJEXT) cluster_functions.$(OBJEXT) \
-	common.$(OBJEXT) sacctmgr.$(OBJEXT) user_functions.$(OBJEXT)
+	common.$(OBJEXT) file_functions.$(OBJEXT) sacctmgr.$(OBJEXT) \
+	user_functions.$(OBJEXT)
 sacctmgr_OBJECTS = $(am_sacctmgr_OBJECTS)
 am__DEPENDENCIES_1 =
 sacctmgr_DEPENDENCIES = $(top_builddir)/src/common/libcommon.o \
@@ -272,6 +273,7 @@ sacctmgr_SOURCES = \
 	association_functions.c	\
 	cluster_functions.c	\
 	common.c                \
+	file_functions.c	\
 	sacctmgr.c sacctmgr.h	\
 	user_functions.c	
 
@@ -356,6 +358,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/association_functions.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cluster_functions.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_functions.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sacctmgr.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user_functions.Po@am__quote@
 
diff --git a/src/sacctmgr/account_functions.c b/src/sacctmgr/account_functions.c
index 876d82beb22d5014f91619c76fa572f9fba095ce..43df7c633d120743e6488820b7f726e3a047d2ea 100644
--- a/src/sacctmgr/account_functions.c
+++ b/src/sacctmgr/account_functions.c
@@ -52,8 +52,10 @@ static int _set_cond(int *start, int argc, char *argv[],
 		if (strncasecmp (argv[i], "Set", 3) == 0) {
 			i--;
 			break;
-		} else if (strncasecmp (argv[i], "WithAssoc", 4) == 0) {
+		} else if (strncasecmp (argv[i], "WithAssoc", 5) == 0) {
 			acct_cond->with_assocs = 1;
+		} else if (strncasecmp (argv[i], "WithCoordinators", 5) == 0) {
+			acct_cond->with_coords = 1;
 		} else if(!end && !strncasecmp(argv[i], "where", 5)) {
 			continue;
 		} else if(!end) {
@@ -179,69 +181,6 @@ static int _set_rec(int *start, int argc, char *argv[],
 	return 0;
 }
 
-/* static void _print_cond(acct_account_cond_t *acct_cond) */
-/* { */
-/* 	ListIterator itr = NULL; */
-/* 	char *tmp_char = NULL; */
-
-/* 	if(!acct_cond) { */
-/* 		error("no acct_account_cond_t * given"); */
-/* 		return; */
-/* 	} */
-
-/* 	if(acct_cond->acct_list && list_count(acct_cond->acct_list)) { */
-/* 		itr = list_iterator_create(acct_cond->acct_list); */
-/* 		printf("  Names       = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("             or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(acct_cond->description_list */
-/* 	   && list_count(acct_cond->description_list)) { */
-/* 		itr = list_iterator_create(acct_cond->description_list); */
-/* 		printf("  Description = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("             or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(acct_cond->organization_list */
-/* 	   && list_count(acct_cond->organization_list)) { */
-/* 		itr = list_iterator_create(acct_cond->organization_list); */
-/* 		printf("  Organization = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("             or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(acct_cond->qos != ACCT_QOS_NOTSET) */
-/* 		printf("  Qos     = %s\n",  */
-/* 		       acct_qos_str(acct_cond->qos)); */
-/* } */
-
-/* static void _print_rec(acct_account_rec_t *acct) */
-/* { */
-/* 	if(!acct) { */
-/* 		error("no acct_account_rec_t * given"); */
-/* 		return; */
-/* 	} */
-	
-/* 	if(acct->name)  */
-/* 		printf("  Name         = %s\n", acct->name);	 */
-		
-/* 	if(acct->description)  */
-/* 		printf("  Description  = %s\n", acct->description); */
-
-/* 	if(acct->organization)  */
-/* 		printf("  Organization = %s\n", acct->organization); */
-		
-/* 	if(acct->qos != ACCT_QOS_NOTSET) */
-/* 		printf("  Qos     = %s\n",  */
-/* 		       acct_qos_str(acct->qos)); */
-
-/* } */
-
 extern int sacctmgr_add_account(int argc, char *argv[])
 {
 	int rc = SLURM_SUCCESS;
@@ -650,6 +589,7 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 	enum {
 		PRINT_ACCOUNT,
 		PRINT_CLUSTER,
+		PRINT_COORDS,
 		PRINT_DESC,
 		PRINT_FAIRSHARE,
 		PRINT_ID,
@@ -659,6 +599,8 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 		PRINT_MAXW,
 		PRINT_ORG,
 		PRINT_QOS,
+		PRINT_QOS_GOLD,
+		PRINT_QOS_RAW,
 		PRINT_PID,
 		PRINT_PNAME,
 		PRINT_PART,
@@ -682,7 +624,10 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 		addto_char_list(format_list, "A,D,O,Q");
 		if(acct_cond->with_assocs)
 			addto_char_list(format_list,
-					"C,ParentN,U,F,MaxC,MaxJ,MaxN,MaxW");
+					"Cl,ParentN,U,F,MaxC,MaxJ,MaxN,MaxW");
+			
+		if(acct_cond->with_coords)
+			addto_char_list(format_list, "Coord");
 			
 	}
 	acct_list = acct_storage_g_get_accounts(db_conn, acct_cond);	
@@ -703,11 +648,16 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 			field->name = xstrdup("Account");
 			field->len = 10;
 			field->print_routine = print_fields_str;
-		} else if(!strncasecmp("Cluster", object, 1)) {
+		} else if(!strncasecmp("Cluster", object, 2)) {
 			field->type = PRINT_CLUSTER;
 			field->name = xstrdup("Cluster");
 			field->len = 10;
 			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Coordinators", object, 2)) {
+			field->type = PRINT_COORDS;
+			field->name = xstrdup("Coordinators");
+			field->len = 20;
+			field->print_routine = sacctmgr_print_coord_list;
 		} else if(!strncasecmp("Description", object, 1)) {
 			field->type = PRINT_DESC;
 			field->name = xstrdup("Descr");
@@ -748,6 +698,16 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 			field->name = xstrdup("Org");
 			field->len = 20;
 			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("QOSGOLD", object, 4)) {
+			field->type = PRINT_QOS_GOLD;
+			field->name = xstrdup("QOS_GOLD");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("QOSRAW", object, 4)) {
+			field->type = PRINT_QOS_RAW;
+			field->name = xstrdup("QOS_RAW");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
 		} else if(!strncasecmp("QOS", object, 1)) {
 			field->type = PRINT_QOS;
 			field->name = xstrdup("QOS");
@@ -776,6 +736,7 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 		list_append(print_fields_list, field);		
 	}
 	list_iterator_destroy(itr);
+	list_destroy(format_list);
 
 	itr = list_iterator_create(acct_list);
 	itr2 = list_iterator_create(print_fields_list);
@@ -799,6 +760,12 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 							SLURM_PRINT_VALUE,
 							field, assoc->cluster);
 						break;
+					case PRINT_COORDS:
+						field->print_routine(
+							SLURM_PRINT_VALUE,
+							field,
+							acct->coordinators);
+						break;
 					case PRINT_DESC:
 						field->print_routine(
 							SLURM_PRINT_VALUE,
@@ -850,7 +817,20 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 						field->print_routine(
 							SLURM_PRINT_VALUE,
 							field, 
-							acct_qos_str(acct->qos));
+							acct_qos_str(
+								acct->qos));
+						break;
+					case PRINT_QOS_GOLD:
+						field->print_routine(
+							SLURM_PRINT_VALUE,
+							field,
+							acct->qos-1);
+						break;
+					case PRINT_QOS_RAW:
+						field->print_routine(
+							SLURM_PRINT_VALUE,
+							field,
+							acct->qos);
 						break;
 					case PRINT_PID:
 						field->print_routine(
@@ -896,6 +876,12 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 						SLURM_PRINT_VALUE,
 						field, NULL);
 					break;
+				case PRINT_COORDS:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field,
+						acct->coordinators);
+					break;
 				case PRINT_DESC:
 					field->print_routine(
 						SLURM_PRINT_VALUE,
@@ -941,6 +927,16 @@ extern int sacctmgr_list_account(int argc, char *argv[])
 						SLURM_PRINT_VALUE,
 						field, acct_qos_str(acct->qos));
 					break;
+				case PRINT_QOS_GOLD:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						acct->qos-1);
+					break;
+				case PRINT_QOS_RAW:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						acct->qos);
+					break;
 				case PRINT_PID:
 					field->print_routine(
 						SLURM_PRINT_VALUE,
diff --git a/src/sacctmgr/association_functions.c b/src/sacctmgr/association_functions.c
index c7ae5a630f35df8d653cc66b8d8d5cf2c7a79495..9a754fdefdff2d679e196ec4b4abf0899b64b6b7 100644
--- a/src/sacctmgr/association_functions.c
+++ b/src/sacctmgr/association_functions.c
@@ -37,6 +37,82 @@
 \*****************************************************************************/
 
 #include "src/sacctmgr/sacctmgr.h"
+bool tree_display = 0;
+
+typedef struct {
+	char *name;
+	char *print_name;
+	char *spaces;
+} print_acct_t;
+
+static void _destroy_print_acct(void *object)
+{
+	print_acct_t *print_acct = (print_acct_t *)object;
+	if(print_acct) {
+		xfree(print_acct->name);
+		xfree(print_acct->print_name);
+		xfree(print_acct->spaces);
+		xfree(print_acct);
+	}
+}
+
+static char *_get_print_acct_name(char *name, char *parent, char *cluster, 
+				  List tree_list)
+{
+	ListIterator itr = NULL;
+	print_acct_t *print_acct = NULL;
+	print_acct_t *par_print_acct = NULL;
+	static char *ret_name = NULL;
+	static char *last_name = NULL, *last_cluster = NULL;
+
+
+	if(!tree_list) {
+		return NULL;
+	}
+	
+	itr = list_iterator_create(tree_list);
+	while((print_acct = list_next(itr))) {
+		if(!strcmp(name, print_acct->name)) {
+			ret_name = print_acct->print_name;
+			break;
+		} else if(parent && !strcmp(parent, print_acct->name)) {
+			par_print_acct = print_acct;
+		}
+	}
+	list_iterator_destroy(itr);
+	
+	if(parent && print_acct) {
+		return ret_name;
+	} 
+
+	print_acct = xmalloc(sizeof(print_acct_t));
+	print_acct->name = xstrdup(name);
+	if(par_print_acct) {
+		print_acct->spaces =
+			xstrdup_printf(" %s", par_print_acct->spaces);
+	} else {
+		print_acct->spaces = xstrdup("");
+	}
+
+	/* user account */
+	if(name[0] == '|')
+		print_acct->print_name = xstrdup_printf("%s%s", 
+							print_acct->spaces, 
+							parent);	
+	else
+		print_acct->print_name = xstrdup_printf("%s%s", 
+							print_acct->spaces, 
+							name);	
+	
+
+	list_append(tree_list, print_acct);
+
+	ret_name = print_acct->print_name;
+	last_name = name;
+	last_cluster = cluster;
+
+	return print_acct->print_name;
+}
 
 static int _set_cond(int *start, int argc, char *argv[],
 		     acct_association_cond_t *association_cond,
@@ -47,7 +123,9 @@ static int _set_cond(int *start, int argc, char *argv[],
 
 	for (i=(*start); i<argc; i++) {
 		end = parse_option_end(argv[i]);
-		if(!end && !strncasecmp(argv[i], "where", 5)) {
+		if (!end && strncasecmp (argv[i], "Tree", 4) == 0) {
+			tree_display = 1;
+		} else if(!end && !strncasecmp(argv[i], "where", 5)) {
 			continue;
 		} else if(!end) {
 			addto_char_list(association_cond->id_list, argv[i]);
@@ -90,108 +168,144 @@ static int _set_cond(int *start, int argc, char *argv[],
 	return set;
 }
 
-/* static void _print_cond(acct_association_cond_t *association_cond) */
-/* { */
-/* 	ListIterator itr = NULL; */
-/* 	char *tmp_char = NULL; */
-
-/* 	if(!association_cond) { */
-/* 		error("no acct_association_cond_t * given"); */
-/* 		return; */
-/* 	} */
-
-/* 	if(association_cond->id_list && list_count(association_cond->id_list)) { */
-/* 		itr = list_iterator_create(association_cond->id_list); */
-/* 		printf("  Id        = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("           or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(association_cond->user_list */
-/* 	   && list_count(association_cond->user_list)) { */
-/* 		itr = list_iterator_create(association_cond->user_list); */
-/* 		printf("  User      = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("           or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(association_cond->acct_list */
-/* 	   && list_count(association_cond->acct_list)) { */
-/* 		itr = list_iterator_create(association_cond->acct_list); */
-/* 		printf("  Account   = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("           or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(association_cond->cluster_list */
-/* 	   && list_count(association_cond->cluster_list)) { */
-/* 		itr = list_iterator_create(association_cond->cluster_list); */
-/* 		printf("  Cluster   = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("           or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(association_cond->partition_list */
-/* 	   && list_count(association_cond->partition_list)) { */
-/* 		itr = list_iterator_create(association_cond->partition_list); */
-/* 		printf("  Partition = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("           or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(association_cond->parent_account) */
-/* 		printf("  Parent    = %s\n", association_cond->parent_account); */
+/* 
+ * Comparator used for sorting immediate childern of sacctmgr_assocs
+ * 
+ * returns: -1: assoc_a > assoc_b   0: assoc_a == assoc_b   1: assoc_a < assoc_b
+ * 
+ */
 
-/* } */
+static int _sort_childern_list(sacctmgr_assoc_t *assoc_a,
+			       sacctmgr_assoc_t *assoc_b)
+{
+	int diff = 0;
+	/* check to see if this is a user association or an account.
+	 * We want the accounts at the bottom 
+	 */
+	if(assoc_a->assoc->user && !assoc_b->assoc->user)
+		return -1;
+	else if(!assoc_a->assoc->user && assoc_b->assoc->user)
+		return 1;
 
-/* static void _print_rec(acct_association_rec_t *association) */
-/* { */
-/* 	if(!association) { */
-/* 		error("no acct_association_rec_t * given"); */
-/* 		return; */
-/* 	} */
+	diff = strcmp(assoc_a->sort_name, assoc_b->sort_name);
+	if (diff < 0)
+		return -1;
+	else if (diff > 0)
+		return 1;
 	
-/* 	if(association->id)  */
-/* 		printf("  Id         = %u\n", association->id);	 */
-		
-/* 	if(association->user)  */
-/* 		printf("  User       = %s\n", association->user); */
-/* 	if(association->account)  */
-/* 		printf("  Account    = %s\n", association->account); */
-/* 	if(association->cluster)  */
-/* 		printf("  Cluster    = %s\n", association->cluster); */
-/* 	if(association->partition)  */
-/* 		printf("  Partition  = %s\n", association->partition); */
-/* 	if(association->parent_account)  */
-/* 		printf("  Parent     = %s\n", association->parent_account); */
-/* 	if(association->fairshare)  */
-/* 		printf("  FairShare  = %u\n", association->fairshare); */
-/* 	if(association->max_jobs)  */
-/* 		printf("  MaxJobs    = %u\n", association->max_jobs); */
-/* 	if(association->max_nodes_per_job)  */
-/* 		printf("  MaxNodes   = %u\n", association->max_nodes_per_job); */
-/* 	if(association->max_wall_duration_per_job) { */
-/* 		char time_buf[32]; */
-/* 		mins2time_str((time_t) association->max_wall_duration_per_job, */
-/* 			      time_buf, sizeof(time_buf)); */
-/* 		printf("  MaxWall    = %s\n", time_buf); */
-/* 	} */
-/* 	if(association->max_cpu_seconds_per_job)  */
-/* 		printf("  MaxCPUSecs = %u\n", */
-/* 		       association->max_cpu_seconds_per_job); */
-/* } */
+	return 0;
 
-/* extern int sacctmgr_add_association(int argc, char *argv[]) */
-/* { */
-/* 	int rc = SLURM_SUCCESS; */
+}
 
-/* 	return rc; */
-/* } */
+static int _sort_sacctmgr_assoc_list(List sacctmgr_assoc_list)
+{
+	sacctmgr_assoc_t *sacctmgr_assoc = NULL;
+	ListIterator itr;
+
+	if(!list_count(sacctmgr_assoc_list))
+		return SLURM_SUCCESS;
+
+	list_sort(sacctmgr_assoc_list, (ListCmpF)_sort_childern_list);
+
+	itr = list_iterator_create(sacctmgr_assoc_list);
+	while((sacctmgr_assoc = list_next(itr))) {
+		if(list_count(sacctmgr_assoc->childern))
+			_sort_sacctmgr_assoc_list(sacctmgr_assoc->childern);
+	}
+	list_iterator_destroy(itr);
+
+	return SLURM_SUCCESS;
+}
+
+static int _append_ret_list(List ret_list, List sacctmgr_assoc_list)
+{
+	sacctmgr_assoc_t *sacctmgr_assoc = NULL;
+	ListIterator itr;
+
+	if(!ret_list)
+		return SLURM_ERROR;
+
+	if(!list_count(sacctmgr_assoc_list))
+		return SLURM_SUCCESS;
+
+	itr = list_iterator_create(sacctmgr_assoc_list);
+	while((sacctmgr_assoc = list_next(itr))) {
+		list_append(ret_list, sacctmgr_assoc->assoc);
+
+		if(list_count(sacctmgr_assoc->childern)) 
+			_append_ret_list(ret_list, sacctmgr_assoc->childern);
+	}
+	list_iterator_destroy(itr);
+
+	return SLURM_SUCCESS;
+}
+
+static List _sort_assoc_list(List assoc_list)
+{
+	List sacctmgr_assoc_list = sacctmgr_get_hierarchical_list(assoc_list);
+	List ret_list = list_create(NULL);
+
+	_append_ret_list(ret_list, sacctmgr_assoc_list);
+	list_destroy(sacctmgr_assoc_list);
+	
+	return ret_list;
+}
+
+extern List sacctmgr_get_hierarchical_list(List assoc_list)
+{
+	sacctmgr_assoc_t *par_sacctmgr_assoc = NULL;
+	sacctmgr_assoc_t *sacctmgr_assoc = NULL;
+	acct_association_rec_t *assoc = NULL;
+	List total_assoc_list = list_create(NULL);
+	List sacctmgr_assoc_list = list_create(destroy_sacctmgr_assoc);
+	ListIterator itr, itr2;
+
+	itr = list_iterator_create(assoc_list);
+	itr2 = list_iterator_create(total_assoc_list);
+	
+	while((assoc = list_next(itr))) {
+		sacctmgr_assoc = xmalloc(sizeof(sacctmgr_assoc_t));
+		sacctmgr_assoc->childern = list_create(destroy_sacctmgr_assoc);
+		sacctmgr_assoc->assoc = assoc;
+	
+		if(!assoc->parent_id) {
+			sacctmgr_assoc->sort_name = assoc->cluster;
+
+			list_append(sacctmgr_assoc_list, sacctmgr_assoc);
+			list_append(total_assoc_list, sacctmgr_assoc);
+
+			list_iterator_reset(itr2);
+			continue;
+		}
+
+		while((par_sacctmgr_assoc = list_next(itr2))) {
+			if(assoc->parent_id == par_sacctmgr_assoc->assoc->id) 
+				break;
+		}
+
+		if(assoc->user)
+			sacctmgr_assoc->sort_name = assoc->user;
+		else
+			sacctmgr_assoc->sort_name = assoc->acct;
+
+		if(!par_sacctmgr_assoc) 
+			list_append(sacctmgr_assoc_list, sacctmgr_assoc);
+		else
+			list_append(par_sacctmgr_assoc->childern,
+				    sacctmgr_assoc);
+
+		list_append(total_assoc_list, sacctmgr_assoc);
+		list_iterator_reset(itr2);
+	}
+	list_iterator_destroy(itr);
+	list_iterator_destroy(itr2);
+
+	list_destroy(total_assoc_list);
+//	info("got %d", list_count(sacctmgr_assoc_list));
+	_sort_sacctmgr_assoc_list(sacctmgr_assoc_list);
+
+	return sacctmgr_assoc_list;
+}
 
 extern int sacctmgr_list_association(int argc, char *argv[])
 {
@@ -199,11 +313,14 @@ extern int sacctmgr_list_association(int argc, char *argv[])
 	acct_association_cond_t *assoc_cond =
 		xmalloc(sizeof(acct_association_cond_t));
 	List assoc_list = NULL;
+	List first_list = NULL;
 	acct_association_rec_t *assoc = NULL;
 	int i=0;
 	ListIterator itr = NULL;
 	ListIterator itr2 = NULL;
-	char *object;
+	char *object = NULL;
+	char *print_acct = NULL, *last_cluster = NULL;
+	List tree_list = NULL;
 
 	print_field_t *field = NULL;
 
@@ -234,13 +351,15 @@ extern int sacctmgr_list_association(int argc, char *argv[])
 
 	assoc_list = acct_storage_g_get_associations(db_conn, assoc_cond);
 	destroy_acct_association_cond(assoc_cond);
-	
+
 	if(!assoc_list) {
 		printf(" Problem with query.\n");
 		list_destroy(format_list);
 		return SLURM_ERROR;
 	}
 	print_fields_list = list_create(destroy_print_field);
+	first_list = assoc_list;
+	assoc_list = _sort_assoc_list(first_list);
 
 	if(!list_count(format_list)) 
 		addto_char_list(format_list, "C,A,U,F,MaxC,MaxJ,MaxN,MaxW");
@@ -251,7 +370,10 @@ extern int sacctmgr_list_association(int argc, char *argv[])
 		if(!strncasecmp("Account", object, 1)) {
 			field->type = PRINT_ACCOUNT;
 			field->name = xstrdup("Account");
-			field->len = 10;
+			if(tree_display)
+				field->len = 20;
+			else
+				field->len = 10;
 			field->print_routine = print_fields_str;
 		} else if(!strncasecmp("Cluster", object, 1)) {
 			field->type = PRINT_CLUSTER;
@@ -316,17 +438,47 @@ extern int sacctmgr_list_association(int argc, char *argv[])
 		list_append(print_fields_list, field);		
 	}
 	list_iterator_destroy(itr);
+	list_destroy(format_list);
 
 	itr = list_iterator_create(assoc_list);
 	itr2 = list_iterator_create(print_fields_list);
 	print_fields_header(print_fields_list);
 
 	while((assoc = list_next(itr))) {
+		if(!last_cluster || strcmp(last_cluster, assoc->cluster)) {
+			if(tree_list) {
+				list_flush(tree_list);
+			} else {
+				tree_list = list_create(_destroy_print_acct);
+			}
+			last_cluster = assoc->cluster;
+		} 
 		while((field = list_next(itr2))) {
 			switch(field->type) {
 			case PRINT_ACCOUNT:
+				if(tree_display) {
+					char *local_acct = NULL;
+					char *parent_acct = NULL;
+					if(assoc->user) {
+						local_acct = xstrdup_printf(
+							"|%s", assoc->acct);
+						parent_acct = assoc->acct;
+					} else {
+						local_acct =
+							xstrdup(assoc->acct);
+						parent_acct = 
+							assoc->parent_acct;
+					}
+					print_acct = _get_print_acct_name(
+						local_acct,
+						parent_acct,
+						assoc->cluster, tree_list);
+					xfree(local_acct);
+				} else {
+					print_acct = assoc->acct;
+				}
 				field->print_routine(SLURM_PRINT_VALUE, field, 
-						     assoc->acct);
+						     print_acct);
 				break;
 			case PRINT_CLUSTER:
 				field->print_routine(SLURM_PRINT_VALUE, field,
@@ -382,8 +534,12 @@ extern int sacctmgr_list_association(int argc, char *argv[])
 		printf("\n");
 	}
 
+	if(tree_list) 
+		list_destroy(tree_list);
+			
 	list_iterator_destroy(itr2);
 	list_iterator_destroy(itr);
+	list_destroy(first_list);
 	list_destroy(assoc_list);
 	list_destroy(print_fields_list);
 	return rc;
diff --git a/src/sacctmgr/cluster_functions.c b/src/sacctmgr/cluster_functions.c
index f3baedd52d83a1003e1b8d9e1daa94c7b0b2bfc0..2c0ac1653ba115fd781da37c8e798336c1e274c1 100644
--- a/src/sacctmgr/cluster_functions.c
+++ b/src/sacctmgr/cluster_functions.c
@@ -131,6 +131,7 @@ static int _set_rec(int *start, int argc, char *argv[],
 
 }
 
+
 extern int sacctmgr_add_cluster(int argc, char *argv[])
 {
 	int rc = SLURM_SUCCESS;
@@ -399,6 +400,7 @@ extern int sacctmgr_list_cluster(int argc, char *argv[])
 		list_append(print_fields_list, field);		
 	}
 	list_iterator_destroy(itr);
+	list_destroy(format_list);
 
 	itr = list_iterator_create(cluster_list);
 	itr2 = list_iterator_create(print_fields_list);
@@ -513,7 +515,7 @@ extern int sacctmgr_modify_cluster(int argc, char *argv[])
 				 "Are you sure you want to continue?")) {
 			printf("Aborted\n");
 			destroy_acct_association_rec(assoc);
-			destroy_acct_association_cond(assoc);
+			destroy_acct_association_cond(assoc_cond);
 			return SLURM_SUCCESS;
 		}		
 	}
@@ -646,3 +648,128 @@ extern int sacctmgr_delete_cluster(int argc, char *argv[])
 
 	return rc;
 }
+
+extern int sacctmgr_dump_cluster (int argc, char *argv[])
+{
+	acct_user_cond_t user_cond;
+	acct_association_cond_t assoc_cond;
+	List assoc_list = NULL;
+	List acct_list = NULL;
+	List user_list = NULL;
+	List sacctmgr_assoc_list = NULL;
+	char *cluster_name = NULL;
+	char *file_name = NULL;
+	int i;
+	FILE *fd = NULL;
+
+	for (i=0; i<argc; i++) {
+		int end = parse_option_end(argv[i]);
+		if(!end) {
+			if(cluster_name) {
+				printf(" Can only do one cluster at a time.  "
+				       "Already doing %s\n", cluster_name);
+				continue;
+			}
+			cluster_name = xstrdup(argv[i]+end);
+		} else if (strncasecmp (argv[i], "File", 1) == 0) {
+			if(file_name) {
+				printf(" File name already set to %s\n",
+				       file_name);
+				continue;
+			}		
+			file_name = xstrdup(argv[i]+end);
+		} else if (strncasecmp (argv[i], "Name", 1) == 0) {
+			if(cluster_name) {
+				printf(" Can only do one cluster at a time.  "
+				       "Already doing %s\n", cluster_name);
+				continue;
+			}
+			cluster_name = xstrdup(argv[i]+end);
+		} else {
+			printf(" Unknown option: %s\n", argv[i]);
+		}		
+	}
+
+	if(!cluster_name) {
+		printf(" We need a cluster to dump.\n");
+		return SLURM_ERROR;
+	}
+
+	if(!file_name) {
+		file_name = xstrdup_printf("./%s.cfg", cluster_name);
+		printf(" No filename given, using %s.\n", file_name);
+	}
+
+	memset(&assoc_cond, 0, sizeof(acct_association_cond_t));
+	assoc_cond.without_parent_limits = 1;
+	assoc_cond.cluster_list = list_create(NULL);
+	list_append(assoc_cond.cluster_list, cluster_name);
+
+	assoc_list = acct_storage_g_get_associations(db_conn, &assoc_cond);
+
+	list_destroy(assoc_cond.cluster_list);
+	if(!assoc_list) {
+		printf(" Problem with query.\n");
+		xfree(cluster_name);
+		return SLURM_ERROR;
+	} else if(!list_count(assoc_list)) {
+		printf(" Cluster %s returned nothing.", cluster_name);
+		xfree(cluster_name);
+		return SLURM_ERROR;
+	}
+
+	sacctmgr_assoc_list = sacctmgr_get_hierarchical_list(assoc_list);
+
+	memset(&user_cond, 0, sizeof(acct_user_cond_t));
+	user_cond.with_coords = 1;
+
+	user_list = acct_storage_g_get_users(db_conn, &user_cond);
+
+	acct_list = acct_storage_g_get_accounts(db_conn, NULL);
+
+	
+	fd = fopen(file_name, "w");
+	/* Add header */
+	if(fprintf(fd,
+		   "# To edit this file start with a cluster line "
+		   "for the new cluster\n"
+		   "# Cluster - cluster_name\n"
+		   "# Followed by Accounts you want in this fashion...\n"
+		   "# Account - cs:MaxNodesPerJob=5:MaxJobs=4:"
+		   "MaxProcSecondsPerJob=20:FairShare=399:"
+		   "MaxWallDurationPerJob=40:Description='Computer Science':"
+		   "Organization='LC'\n"
+		   "# Any of the options after a ':' can be left out and "
+		   "they can be in any order.\n"
+		   "# If you want to add any sub accounts just list the "
+		   "Parent THAT HAS ALREADY \n"
+		   "# BEEN CREATED before the account line in this fashion...\n"
+		   "# Parent - cs\n"
+		   "# Account - test:MaxNodesPerJob=1:MaxJobs=1:"
+		   "MaxProcSecondsPerJob=1:FairShare=1:MaxWallDurationPerJob=1:"
+		   "Description='Test Account':Organization='Test'\n"
+		   "# To add users to a account add a line like this after a "
+		   "Parent - line\n"
+		   "# User - lipari:MaxNodesPerJob=2:MaxJobs=3:"
+		   "MaxProcSecondsPerJob=4:FairShare=1:"
+		   "MaxWallDurationPerJob=1\n") < 0) {
+		error("Can't write to file");
+		return SLURM_ERROR;
+	}
+
+	if(fprintf(fd, "Cluster - %s\n", cluster_name) < 0) {
+		error("Can't write to file");
+		return SLURM_ERROR;
+	}
+
+	print_file_sacctmgr_assoc_list(
+		fd, sacctmgr_assoc_list, user_list, acct_list);
+
+	xfree(cluster_name);
+	xfree(file_name);
+	list_destroy(sacctmgr_assoc_list);
+	list_destroy(assoc_list);
+	fclose(fd);
+
+	return SLURM_SUCCESS;
+}
diff --git a/src/sacctmgr/common.c b/src/sacctmgr/common.c
index ee4033af8ed6807a4d6f12022ed1c5f78149e929..68f2960c115f52006f8f68145d9912797fa2ed34 100644
--- a/src/sacctmgr/common.c
+++ b/src/sacctmgr/common.c
@@ -52,7 +52,7 @@ static void *_print_lock_warn(void *no_data)
 	return NULL;
 }
 
-static void nonblock(int state)
+static void _nonblock(int state)
 {
 	struct termios ttystate;
 
@@ -75,6 +75,20 @@ static void nonblock(int state)
 
 }
 
+extern void destroy_sacctmgr_assoc(void *object)
+{
+	/* Most of this is pointers to something else that will be
+	 * destroyed elsewhere.
+	 */
+	sacctmgr_assoc_t *sacctmgr_assoc = (sacctmgr_assoc_t *)object;
+	if(sacctmgr_assoc) {
+		if(sacctmgr_assoc->childern) {
+			list_destroy(sacctmgr_assoc->childern);
+		}
+		xfree(sacctmgr_assoc);
+	}
+}
+
 extern int parse_option_end(char *option)
 {
 	int end = 0;
@@ -96,20 +110,26 @@ extern char *strip_quotes(char *option, int *increased)
 	int end = 0;
 	int i=0, start=0;
 	char *meat = NULL;
+	char quote_c = '\0';
+	int quote = 0;
 
 	if(!option)
 		return NULL;
 
 	/* first strip off the ("|')'s */
-	if (option[i] == '\"' || option[i] == '\'')
+	if (option[i] == '\"' || option[i] == '\'') {
+		quote_c = option[i];
+		quote = 1;
 		i++;
+	}
 	start = i;
 
 	while(option[i]) {
-		if(option[i] == '\"' || option[i] == '\'') {
+		if(quote && option[i] == quote_c) {
 			end++;
 			break;
-		}
+		} else if(option[i] == '\"' || option[i] == '\'')
+			option[i] = '`';
 		i++;
 	}
 	end += i;
@@ -202,7 +222,7 @@ extern int commit_check(char *warning)
 		return 1;
 
 	printf("%s (You have 30 seconds to decide)\n", warning);
-	nonblock(1);
+	_nonblock(1);
 	while(c != 'Y' && c != 'y'
 	      && c != 'N' && c != 'n'
 	      && c != '\n') {
@@ -222,7 +242,7 @@ extern int commit_check(char *warning)
 		c = getchar();
 		printf("\n");
 	}
-	nonblock(0);
+	_nonblock(0);
 	if(ans <= 0) 
 		printf("timeout\n");
 	else if(c == 'Y' || c == 'y') 
@@ -542,3 +562,71 @@ extern int get_uint(char *in_value, uint32_t *out_value, char *type)
 	return SLURM_SUCCESS;
 }
 
+extern void sacctmgr_print_coord_list(type_t type, print_field_t *field,
+				      List value)
+{
+	ListIterator itr = NULL;
+	char *print_this = NULL;
+	acct_coord_rec_t *object = NULL;
+	
+	switch(type) {
+	case SLURM_PRINT_HEADLINE:
+		if(print_fields_parsable_print)
+			printf("%s|", field->name);
+		else
+			printf("%-*.*s ", field->len, field->len, field->name);
+		break;
+	case SLURM_PRINT_UNDERSCORE:
+		if(!print_fields_parsable_print)
+			printf("%-*.*s ", field->len, field->len, 
+			       "---------------------------------------");
+		break;
+	case SLURM_PRINT_VALUE:
+		if(!value || !list_count(value)) {
+			if(print_fields_parsable_print)
+				print_this = xstrdup("");
+			else
+				print_this = xstrdup(" ");
+		} else {
+			list_sort(value, (ListCmpF)sort_coord_list);
+			itr = list_iterator_create(value);
+			while((object = list_next(itr))) {
+				if(print_this) 
+					xstrfmtcat(print_this, ",%s", 
+						   object->name);
+				else 
+					print_this = xstrdup(object->name);
+			}
+			list_iterator_destroy(itr);
+		}
+
+		if(print_fields_parsable_print)
+			printf("%s|", print_this);
+		else {
+			if(strlen(print_this) > field->len) 
+				print_this[field->len-1] = '+';
+			
+			printf("%-*.*s ", field->len, field->len, print_this);
+		}
+		xfree(print_this);
+		break;
+	default:
+		if(print_fields_parsable_print)
+			printf("%s|", "n/a");
+		else
+			printf("%-*s ", field->len, "n/a");
+		break;
+	}
+}
+
+extern int sort_coord_list(acct_coord_rec_t *coord_a, acct_coord_rec_t *coord_b)
+{
+	int diff = strcmp(coord_a->name, coord_b->name);
+
+	if (diff < 0)
+		return -1;
+	else if (diff > 0)
+		return 1;
+	
+	return 0;
+}
diff --git a/src/sacctmgr/file_functions.c b/src/sacctmgr/file_functions.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f949f63f89a77de10b522c775be92cfc3e9ed38
--- /dev/null
+++ b/src/sacctmgr/file_functions.c
@@ -0,0 +1,1870 @@
+/*****************************************************************************\
+ *  cluster_functions.c - functions dealing with clusters in the
+ *                        accounting system.
+ *****************************************************************************
+ *  Copyright (C) 2008 Lawrence Livermore National Security.
+ *  Copyright (C) 2002-2007 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Danny Auble <da@llnl.gov>
+ *  LLNL-CODE-402394.
+ *  
+ *  This file is part of SLURM, a resource management program.
+ *  For details, see <http://www.llnl.gov/linux/slurm/>.
+ *  
+ *  SLURM 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.
+ *
+ *  In addition, as a special exception, the copyright holders give permission 
+ *  to link the code of portions of this program with the OpenSSL library under
+ *  certain conditions as described in each individual source file, and 
+ *  distribute linked combinations including the two. You must obey the GNU 
+ *  General Public License in all respects for all of the code used other than 
+ *  OpenSSL. If you modify file(s) with this exception, you may extend this 
+ *  exception to your version of the file(s), but you are not obligated to do 
+ *  so. If you do not wish to do so, delete this exception statement from your
+ *  version.  If you delete this exception statement from all source files in 
+ *  the program, then also delete it here.
+ *  
+ *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ *  details.
+ *  
+ *  You should have received a copy of the GNU General Public License along
+ *  with SLURM; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+\*****************************************************************************/
+
+#include "src/sacctmgr/sacctmgr.h"
+
+typedef struct {
+	acct_admin_level_t admin;
+	List coord_list; /* char *list */
+	char *def_acct;
+	char *desc;
+	uint32_t fairshare;
+	uint32_t max_cpu_secs_per_job; 
+	uint32_t max_jobs;
+	uint32_t max_nodes_per_job; 
+	uint32_t max_wall_duration_per_job;
+	char *name;
+	char *org;
+	char *part;
+	acct_qos_level_t qos;
+} sacctmgr_file_opts_t;
+
+enum {
+	PRINT_ACCOUNT,
+	PRINT_ADMIN,
+	PRINT_CLUSTER,
+	PRINT_COORDS,
+	PRINT_DACCT,
+	PRINT_DESC,
+	PRINT_FAIRSHARE,
+	PRINT_ID,
+	PRINT_MAXC,
+	PRINT_MAXJ,
+	PRINT_MAXN,
+	PRINT_MAXW,
+	PRINT_NAME,
+	PRINT_ORG,
+	PRINT_QOS,
+	PRINT_QOS_GOLD,
+	PRINT_QOS_RAW,
+	PRINT_PID,
+	PRINT_PARENT,
+	PRINT_PART,
+	PRINT_USER
+};
+
+typedef enum {
+	MOD_CLUSTER,
+	MOD_ACCT,
+	MOD_USER
+} sacctmgr_mod_type_t;
+
+static int _strip_continuation(char *buf, int len)
+{
+	char *ptr;
+	int bs = 0;
+
+	for (ptr = buf+len-1; ptr >= buf; ptr--) {
+		if (*ptr == '\\')
+			bs++;
+		else if (isspace(*ptr) && bs == 0)
+			continue;
+		else
+			break;
+	}
+	/* Check for an odd number of contiguous backslashes at
+	   the end of the line */
+	if (bs % 2 == 1) {
+		ptr = ptr + bs;
+		*ptr = '\0';
+		return (ptr - buf);
+	} else {
+		return len; /* no continuation */
+	}
+}
+
+/* Strip comments from a line by terminating the string
+ * where the comment begins.
+ * Everything after a non-escaped "#" is a comment.
+ */
+static void _strip_comments(char *line)
+{
+	int i;
+	int len = strlen(line);
+	int bs_count = 0;
+
+	for (i = 0; i < len; i++) {
+		/* if # character is preceded by an even number of
+		 * escape characters '\' */
+		if (line[i] == '#' && (bs_count%2) == 0) {
+			line[i] = '\0';
+ 			break;
+		} else if (line[i] == '\\') {
+			bs_count++;
+		} else {
+			bs_count = 0;
+		}
+	}
+}
+
+/*
+ * Strips any escape characters, "\".  If you WANT a back-slash,
+ * it must be escaped, "\\".
+ */
+static void _strip_escapes(char *line)
+{
+	int i, j;
+	int len = strlen(line);
+
+	for (i = 0, j = 0; i < len+1; i++, j++) {
+		if (line[i] == '\\')
+			i++;
+		line[j] = line[i];
+	}
+}
+
+/*
+ * Reads the next line from the "file" into buffer "buf".
+ *
+ * Concatonates together lines that are continued on
+ * the next line by a trailing "\".  Strips out comments,
+ * replaces escaped "\#" with "#", and replaces "\\" with "\".
+ */
+static int _get_next_line(char *buf, int buf_size, FILE *file)
+{
+	char *ptr = buf;
+	int leftover = buf_size;
+	int read_size, new_size;
+	int lines = 0;
+
+	while (fgets(ptr, leftover, file)) {
+		lines++;
+		_strip_comments(ptr);
+		read_size = strlen(ptr);
+		new_size = _strip_continuation(ptr, read_size);
+		if (new_size < read_size) {
+			ptr += new_size;
+			leftover -= new_size;
+		} else { /* no continuation */
+			break;
+		}
+	}
+	/* _strip_cr_nl(buf); */ /* not necessary */
+	_strip_escapes(buf);
+	
+	return lines;
+}
+
+static void _destroy_sacctmgr_file_opts(void *object)
+{
+	sacctmgr_file_opts_t *file_opts = (sacctmgr_file_opts_t *)object;
+
+	if(file_opts) {
+		if(file_opts->coord_list)
+			list_destroy(file_opts->coord_list);
+		xfree(file_opts->def_acct);
+		xfree(file_opts->desc);
+		xfree(file_opts->name);
+		xfree(file_opts->org);
+		xfree(file_opts->part);
+		xfree(file_opts);		
+	}
+}
+
+static sacctmgr_file_opts_t *_parse_options(char *options)
+{
+	int start=0, i=0, end=0, mins, quote = 0;
+ 	char *sub = NULL;
+	sacctmgr_file_opts_t *file_opts = xmalloc(sizeof(sacctmgr_file_opts_t));
+	char *option = NULL;
+	char quote_c = '\0';
+
+	file_opts->fairshare = 1;
+	file_opts->max_cpu_secs_per_job = INFINITE;
+	file_opts->max_jobs = INFINITE;
+	file_opts->max_nodes_per_job = INFINITE;
+	file_opts->max_wall_duration_per_job = INFINITE;
+	file_opts->qos = ACCT_QOS_NORMAL;
+	file_opts->admin = ACCT_ADMIN_NONE;
+
+	while(options[i]) {
+		quote = 0;
+		start=i;
+		
+		while(options[i] && options[i] != ':' && options[i] != '\n') {
+			if(options[i] == '"' || options[i] == '\'') {
+				if(quote) {
+					if(options[i] == quote_c)
+						quote = 0;
+				} else {
+					quote = 1;
+					quote_c = options[i];
+				}
+			}
+			i++;
+		}
+		if(quote) {
+			while(options[i] && options[i] != quote_c) 
+				i++;
+			if(!options[i])
+				fatal("There is a problem with option "
+				      "%s with quotes.", option);
+			i++;
+		}
+
+		if(i-start <= 0)
+			goto next_col;
+
+		sub = xstrndup(options+start, i-start);
+		end = parse_option_end(sub);
+		
+		option = strip_quotes(sub+end, NULL);
+		if(!end) {
+			if(file_opts->name) {
+				printf(" Bad format on %s: "
+				       "End your option with "
+				       "an '=' sign\n", sub);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+			file_opts->name = xstrdup(option);
+		} else if (strncasecmp (sub, "AdminLevel", 2) == 0) {
+			file_opts->admin = str_2_acct_admin_level(option);
+		} else if (strncasecmp (sub, "Coordinator", 2) == 0) {
+			if(!file_opts->coord_list)
+				file_opts->coord_list =
+					list_create(slurm_destroy_char);
+			addto_char_list(file_opts->coord_list, option);
+		} else if (strncasecmp (sub, "DefaultAccount", 3) == 0) {
+			file_opts->def_acct = xstrdup(option);
+		} else if (strncasecmp (sub, "Description", 3) == 0) {
+			file_opts->desc = xstrdup(option);
+		} else if (strncasecmp (sub, "FairShare", 1) == 0) {
+			if (get_uint(option, &file_opts->fairshare, 
+			    "FairShare") != SLURM_SUCCESS) {
+				printf(" Bad FairShare value: %s\n", option);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+		} else if (strncasecmp (sub, "MaxCPUSec", 4) == 0
+			   || strncasecmp (sub, "MaxProcSec", 4) == 0) {
+			if (get_uint(option, &file_opts->max_cpu_secs_per_job,
+			    "MaxCPUSec") != SLURM_SUCCESS) {
+				printf(" Bad MaxCPUSec value: %s\n", option);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+		} else if (strncasecmp (sub, "MaxJobs", 4) == 0) {
+			if (get_uint(option, &file_opts->max_jobs,
+			    "MaxJobs") != SLURM_SUCCESS) {
+				printf(" Bad MaxJobs value: %s\n", option);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+		} else if (strncasecmp (sub, "MaxNodes", 4) == 0) {
+			if (get_uint(option, &file_opts->max_nodes_per_job,
+			    "MaxNodes") != SLURM_SUCCESS) {
+				printf(" Bad MaxNodes value: %s\n", option);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+		} else if (strncasecmp (sub, "MaxWall", 4) == 0) {
+			mins = time_str2mins(option);
+			if (mins >= 0) {
+				file_opts->max_wall_duration_per_job 
+					= (uint32_t) mins;
+			} else if (strcmp(option, "-1") == 0) {
+				file_opts->max_wall_duration_per_job = INFINITE;
+			} else {
+				printf(" Bad MaxWall time format: %s\n", 
+					option);
+				_destroy_sacctmgr_file_opts(file_opts);
+				break;
+			}
+		} else if (strncasecmp (sub, "Organization", 1) == 0) {
+			file_opts->org = xstrdup(option);
+		} else if (strncasecmp (sub, "QosLevel", 1) == 0
+			   || strncasecmp (sub, "Expedite", 1) == 0) {
+			file_opts->qos = str_2_acct_qos(option);
+		} else {
+			printf(" Unknown option: %s\n", sub);
+		}
+
+		xfree(sub);
+		xfree(option);
+
+	next_col:
+		if(options[i] == ':')
+			i++;
+		else
+			break;
+	}
+	
+	xfree(sub);
+	xfree(option);
+
+	if(!file_opts->name) {
+		printf(" error: No name given\n");
+		_destroy_sacctmgr_file_opts(file_opts);
+	}
+	return file_opts;
+}
+
+static List _set_up_print_fields(List format_list)
+{
+	ListIterator itr = NULL;
+	List print_fields_list = NULL;
+	print_field_t *field = NULL;
+	char *object = NULL;
+
+	print_fields_list = list_create(destroy_print_field);
+	itr = list_iterator_create(format_list);
+	while((object = list_next(itr))) {
+		field = xmalloc(sizeof(print_field_t));
+		if(!strncasecmp("Account", object, 2)) {
+			field->type = PRINT_ACCOUNT;
+			field->name = xstrdup("Account");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("AdminLevel", object, 2)) {
+			field->type = PRINT_ADMIN;
+			field->name = xstrdup("Admin");
+			field->len = 9;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Cluster", object, 2)) {
+			field->type = PRINT_CLUSTER;
+			field->name = xstrdup("Cluster");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Coordinators", object, 2)) {
+			field->type = PRINT_COORDS;
+			field->name = xstrdup("Coord Accounts");
+			field->len = 20;
+			field->print_routine = sacctmgr_print_coord_list;
+		} else if(!strncasecmp("Default", object, 3)) {
+			field->type = PRINT_DACCT;
+			field->name = xstrdup("Def Acct");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Description", object, 3)) {
+			field->type = PRINT_DESC;
+			field->name = xstrdup("Descr");
+			field->len = 20;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("FairShare", object, 1)) {
+			field->type = PRINT_FAIRSHARE;
+			field->name = xstrdup("FairShare");
+			field->len = 9;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("ID", object, 1)) {
+			field->type = PRINT_ID;
+			field->name = xstrdup("ID");
+			field->len = 6;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("MaxCPUSecs", object, 4)) {
+			field->type = PRINT_MAXC;
+			field->name = xstrdup("MaxCPUSecs");
+			field->len = 11;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("MaxJobs", object, 4)) {
+			field->type = PRINT_MAXJ;
+			field->name = xstrdup("MaxJobs");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("MaxNodes", object, 4)) {
+			field->type = PRINT_MAXN;
+			field->name = xstrdup("MaxNodes");
+			field->len = 8;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("MaxWall", object, 4)) {
+			field->type = PRINT_MAXW;
+			field->name = xstrdup("MaxWall");
+			field->len = 11;
+			field->print_routine = print_fields_time;
+		} else if(!strncasecmp("Name", object, 1)) {
+			field->type = PRINT_NAME;
+			field->name = xstrdup("Name");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Organization", object, 1)) {
+			field->type = PRINT_ORG;
+			field->name = xstrdup("Org");
+			field->len = 20;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("QOSGOLD", object, 4)) {
+			field->type = PRINT_QOS_GOLD;
+			field->name = xstrdup("QOS_GOLD");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("QOSRAW", object, 4)) {
+			field->type = PRINT_QOS_RAW;
+			field->name = xstrdup("QOS_RAW");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("QOS", object, 1)) {
+			field->type = PRINT_QOS;
+			field->name = xstrdup("QOS");
+			field->len = 9;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Parent", object, 4)) {
+			field->type = PRINT_PARENT;
+			field->name = xstrdup("Parent");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Partition", object, 4)) {
+			field->type = PRINT_PART;
+			field->name = xstrdup("Partition");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("User", object, 1)) {
+			field->type = PRINT_USER;
+			field->name = xstrdup("User");
+			field->len = 10;
+			field->print_routine = print_fields_str;
+		} else {
+			printf("Unknown field '%s'\n", object);
+			xfree(field);
+			continue;
+		}
+		list_append(print_fields_list, field);		
+	}
+	list_iterator_destroy(itr);
+	return print_fields_list;
+}
+
+static int _print_out_assoc(List assoc_list, bool user)
+{
+	List format_list = NULL;
+	List print_fields_list = NULL;
+	ListIterator itr, itr2;
+	print_field_t *field = NULL;
+	acct_association_rec_t *assoc = NULL;
+	int rc = SLURM_SUCCESS;
+
+	if(!assoc_list || !list_count(assoc_list))
+		return rc;
+	
+	format_list = list_create(slurm_destroy_char);
+	if(user)
+		addto_char_list(format_list,
+				"User,Account,F,MaxC,MaxJ,MaxN,MaxW");
+	else 
+		addto_char_list(format_list,
+				"Account,Parent,F,MaxC,MaxJ,MaxN,MaxW");
+	
+	print_fields_list = _set_up_print_fields(format_list);
+	list_destroy(format_list);
+	
+	print_fields_header(print_fields_list);
+	
+	itr = list_iterator_create(assoc_list);
+	itr2 = list_iterator_create(print_fields_list);
+	while((assoc = list_next(itr))) {
+		while((field = list_next(itr2))) {
+			switch(field->type) {
+			case PRINT_ACCOUNT:
+				field->print_routine(SLURM_PRINT_VALUE, field,
+						     assoc->acct);
+				break;
+			case PRINT_FAIRSHARE:
+				field->print_routine(SLURM_PRINT_VALUE, field,
+						     assoc->fairshare);
+				break;
+			case PRINT_MAXC:
+				field->print_routine(
+					SLURM_PRINT_VALUE, field,
+					assoc->max_cpu_secs_per_job);
+				break;
+			case PRINT_MAXJ:
+				field->print_routine(SLURM_PRINT_VALUE, field, 
+						     assoc->max_jobs);
+				break;
+			case PRINT_MAXN:
+				field->print_routine(SLURM_PRINT_VALUE, field,
+						     assoc->max_nodes_per_job);
+				break;
+			case PRINT_MAXW:
+				field->print_routine(
+					SLURM_PRINT_VALUE, field,
+					assoc->max_wall_duration_per_job);
+				break;
+			case PRINT_PARENT:
+				field->print_routine(SLURM_PRINT_VALUE, field,
+						     assoc->parent_acct);
+				break;
+			case PRINT_PART:
+				field->print_routine(SLURM_PRINT_VALUE, field,
+						     assoc->partition);
+				break;
+			case PRINT_USER:
+				field->print_routine(SLURM_PRINT_VALUE, field, 
+						     assoc->user);
+				break;
+			default:
+				break;
+			}
+		}
+		list_iterator_reset(itr2);
+		printf("\n");
+	}
+	list_iterator_destroy(itr);
+	list_iterator_destroy(itr2);
+	list_destroy(print_fields_list);
+	rc = acct_storage_g_add_associations(db_conn, my_uid, assoc_list);
+	printf("---------------------------------------------------\n\n");
+
+	return rc;
+}
+
+static int _mod_cluster(sacctmgr_file_opts_t *file_opts,
+			acct_cluster_rec_t *cluster)
+{
+	int changed = 0;
+	acct_association_rec_t mod_assoc;
+	acct_association_cond_t assoc_cond;
+	char *my_info = NULL;
+
+	memset(&mod_assoc, 0, sizeof(acct_association_rec_t));
+
+	mod_assoc.fairshare = NO_VAL;
+	mod_assoc.max_cpu_secs_per_job = NO_VAL;
+	mod_assoc.max_jobs = NO_VAL;
+	mod_assoc.max_nodes_per_job = NO_VAL;
+	mod_assoc.max_wall_duration_per_job = NO_VAL;
+
+	memset(&assoc_cond, 0, sizeof(acct_association_cond_t));
+
+	assoc_cond.fairshare = NO_VAL;
+	assoc_cond.max_cpu_secs_per_job = NO_VAL;
+	assoc_cond.max_jobs = NO_VAL;
+	assoc_cond.max_nodes_per_job = NO_VAL;
+	assoc_cond.max_wall_duration_per_job = NO_VAL;
+
+	if(cluster->default_fairshare != file_opts->fairshare) {
+		mod_assoc.fairshare = file_opts->fairshare;
+		changed = 1;
+		xstrfmtcat(my_info, " Changed Cluster default for "
+		       "fairshare from %d -> %d\n",
+		       cluster->default_fairshare,
+		       file_opts->fairshare);
+	}
+	if(cluster->default_max_cpu_secs_per_job != 
+	   file_opts->max_cpu_secs_per_job) {
+		mod_assoc.max_cpu_secs_per_job = 
+			file_opts->max_cpu_secs_per_job;
+		changed = 1;
+		printf(" Changed Cluster default for "
+		       "MaxCPUSecsPerJob from %d -> %d\n",
+		       cluster->default_max_cpu_secs_per_job,
+		       file_opts->max_cpu_secs_per_job);
+	}
+	if(cluster->default_max_jobs != file_opts->max_jobs) {
+		mod_assoc.max_jobs = file_opts->max_jobs;
+		changed = 1;
+		printf(" Changed Cluster default for "
+		       "MaxJobs from %d -> %d\n",
+		       cluster->default_max_jobs,
+		       file_opts->max_jobs);
+	}
+	if(cluster->default_max_nodes_per_job != file_opts->max_nodes_per_job) {
+		mod_assoc.max_nodes_per_job = file_opts->max_nodes_per_job;
+		changed = 1;
+		printf(" Changed Cluster default for "
+		       "MaxNodesPerJob from %d -> %d\n",
+		       cluster->default_max_nodes_per_job, 
+		       file_opts->max_nodes_per_job);
+	}
+	if(cluster->default_max_wall_duration_per_job !=
+	   file_opts->max_wall_duration_per_job) {
+		mod_assoc.max_wall_duration_per_job =
+			file_opts->max_wall_duration_per_job;
+		changed = 1;
+		printf(" Changed Cluster default for "
+		       "MaxWallDurationPerJob from %d -> %d\n",
+		       cluster->default_max_wall_duration_per_job,
+		       file_opts->max_wall_duration_per_job);
+	}
+
+	if(changed) {
+		List ret_list = NULL;
+					
+		assoc_cond.cluster_list = list_create(NULL); 
+		assoc_cond.acct_list = list_create(NULL); 
+					
+		list_push(assoc_cond.cluster_list, cluster->name);
+		list_push(assoc_cond.acct_list, "root");
+					
+		notice_thread_init();
+		ret_list = acct_storage_g_modify_associations(
+			db_conn, my_uid,
+			&assoc_cond, 
+			&mod_assoc);
+		notice_thread_fini();
+					
+		list_destroy(assoc_cond.cluster_list);
+		list_destroy(assoc_cond.acct_list);
+
+/* 		if(ret_list && list_count(ret_list)) { */
+/* 			char *object = NULL; */
+/* 			ListIterator itr = list_iterator_create(ret_list); */
+/* 			printf(" Modified cluster defaults for " */
+/* 			       "associations...\n"); */
+/* 			while((object = list_next(itr)))  */
+/* 				printf("  %s\n", object); */
+/* 			list_iterator_destroy(itr); */
+/* 		} */
+ 
+		if(ret_list) {
+			list_destroy(ret_list);
+		} else
+			changed = 0;
+	}
+
+	return changed;
+}
+
+static int _mod_acct(sacctmgr_file_opts_t *file_opts,
+		     acct_account_rec_t *acct, char *parent)
+{
+	int changed = 0;
+	char *desc = NULL, *org = NULL;
+	acct_account_rec_t mod_acct;
+	acct_account_cond_t acct_cond;
+	
+	memset(&mod_acct, 0, sizeof(acct_account_rec_t));
+	memset(&acct_cond, 0, sizeof(acct_account_cond_t));
+
+	if(file_opts->desc) 
+		desc = xstrdup(file_opts->desc);
+	else
+		desc = xstrdup(file_opts->name);
+	if(strcmp(desc, acct->description)) {
+		printf(" Changed description for account "
+		       "'%s' from '%s' to '%s'\n",
+		       acct->name,
+		       acct->description,
+		       desc);
+		mod_acct.description = desc;
+		changed = 1;
+	}
+				
+	if(file_opts->org)
+		org = xstrdup(file_opts->org);
+	else if(strcmp(parent, "root"))
+		org = xstrdup(parent);
+	else
+		org = xstrdup(file_opts->name);
+	if(strcmp(org, acct->organization)) {
+		printf(" Changed organization for account '%s' "
+		       "from '%s' to '%s'\n",
+		       acct->name,
+		       acct->organization,
+		       org);
+		mod_acct.organization = org;
+		changed = 1;
+	}
+				
+	if(acct->qos != file_opts->qos) {
+		printf(" Changed QOS for account '%s' "
+		       "from '%s' to '%s'\n",
+		       acct->name,
+		       acct_qos_str(acct->qos),
+		       acct_qos_str(file_opts->qos));
+		mod_acct.qos = file_opts->qos;
+		changed = 1;
+	}
+									
+	if(changed) {
+		List ret_list = NULL;
+					
+		acct_cond.acct_list = 
+			list_create(NULL); 
+					
+		list_push(acct_cond.acct_list,
+			  acct->name);
+					
+		notice_thread_init();
+		ret_list = acct_storage_g_modify_accounts(db_conn, my_uid,
+							  &acct_cond, 
+							  &mod_acct);
+		notice_thread_fini();
+	
+					
+		list_destroy(acct_cond.acct_list);
+
+/* 		if(ret_list && list_count(ret_list)) { */
+/* 			char *object = NULL; */
+/* 			ListIterator itr = list_iterator_create(ret_list); */
+/* 			printf(" Modified account defaults for " */
+/* 			       "associations...\n"); */
+/* 			while((object = list_next(itr)))  */
+/* 				printf("  %s\n", object); */
+/* 			list_iterator_destroy(itr); */
+/* 		} */
+ 
+		if(ret_list) {
+			list_destroy(ret_list);
+		} else
+			changed = 0;
+	}
+	xfree(desc);
+	xfree(org);
+	return changed;
+}
+
+static int _mod_user(sacctmgr_file_opts_t *file_opts,
+		     acct_user_rec_t *user, char *parent)
+{
+	int rc;
+	int set = 0;
+	int changed = 0;
+	char *def_acct = NULL;
+	acct_user_rec_t mod_user;
+	acct_user_cond_t user_cond;
+	List ret_list = NULL;
+	
+	memset(&mod_user, 0, sizeof(acct_user_rec_t));
+	memset(&user_cond, 0, sizeof(acct_user_cond_t));
+				
+	user_cond.user_list = list_create(NULL); 
+	list_push(user_cond.user_list, user->name);
+
+	if(file_opts->def_acct)
+		def_acct = xstrdup(file_opts->def_acct);
+	else
+		def_acct = xstrdup(parent);
+
+	if(strcmp(def_acct, user->default_acct)) {
+		printf(" Changed User '%s' "
+		       "default account '%s' -> '%s'\n",
+		       user->name,
+		       user->default_acct,
+		       def_acct);
+		mod_user.default_acct = def_acct;
+		changed = 1;
+	}				
+				
+	if(user->qos != file_opts->qos) {
+		printf(" Changed User '%s' "
+		       "QOS '%s' -> '%s'\n",
+		       user->name,
+		       acct_qos_str(user->qos),
+		       acct_qos_str(file_opts->qos));
+		mod_user.qos = file_opts->qos;
+		changed = 1;
+	}
+									
+	if(user->admin_level != file_opts->admin) {
+		printf(" Changed User '%s' "
+		       "AdminLevel '%s' -> '%s'\n",
+		       user->name,
+		       acct_admin_level_str(
+			       user->admin_level),
+		       acct_admin_level_str(
+			       file_opts->admin));
+		mod_user.admin_level = file_opts->admin;
+		changed = 1;
+	}
+									
+	if(changed) {
+		notice_thread_init();
+		ret_list = acct_storage_g_modify_users(
+			db_conn, my_uid,
+			&user_cond, 
+			&mod_user);
+		notice_thread_fini();
+					
+/* 		if(ret_list && list_count(ret_list)) { */
+/* 			char *object = NULL; */
+/* 			ListIterator itr = list_iterator_create(ret_list); */
+/* 			printf(" Modified user defaults for " */
+/* 			       "associations...\n"); */
+/* 			while((object = list_next(itr)))  */
+/* 				printf("  %s\n", object); */
+/* 			list_iterator_destroy(itr); */
+/* 		} */
+ 
+		if(ret_list) {
+			list_destroy(ret_list);
+			set = 1;
+		} 
+	}
+
+	if((!user->coord_accts || !list_count(user->coord_accts))
+		  && (file_opts->coord_list 
+		      && list_count(file_opts->coord_list))) {
+		ListIterator coord_itr = NULL;
+		char *temp_char = NULL;
+		acct_coord_rec_t *coord = NULL;
+		int first = 1;
+		notice_thread_init();
+		rc = acct_storage_g_add_coord(db_conn, my_uid, 
+					      file_opts->coord_list,
+					      &user_cond);
+		notice_thread_fini();
+
+		user->coord_accts = list_create(destroy_acct_coord_rec);
+		coord_itr = list_iterator_create(file_opts->coord_list);
+		printf(" Making User '%s' coordinator for account(s)",
+		       user->name);
+		while((temp_char = list_next(coord_itr))) {
+			coord = xmalloc(sizeof(acct_coord_rec_t));
+			coord->name = xstrdup(temp_char);
+			coord->direct = 1;
+			list_push(user->coord_accts, coord);
+
+			if(first) {
+				printf(" %s", temp_char);
+				first = 0;
+			} else
+				printf(", %s", temp_char);
+		}
+		list_iterator_destroy(coord_itr);
+		printf("\n");
+		set = 1;
+	} else if((user->coord_accts && list_count(user->coord_accts))
+		  && (file_opts->coord_list 
+		      && list_count(file_opts->coord_list))) {
+		ListIterator coord_itr = NULL;
+		ListIterator char_itr = NULL;
+		char *temp_char = NULL;
+		acct_coord_rec_t *coord = NULL;
+		List add_list = list_create(NULL);
+
+		coord_itr = list_iterator_create(user->coord_accts);
+		char_itr = list_iterator_create(file_opts->coord_list);
+
+		while((temp_char = list_next(char_itr))) {
+			while((coord = list_next(coord_itr))) {
+				if(!coord->direct)
+					continue;
+				if(!strcmp(coord->name, temp_char)) {
+					break;
+				}
+			}
+			if(!coord) {
+				printf(" Making User '%s' coordinator of "
+				       "account '%s'\n",
+				       user->name,
+				       temp_char);
+					
+				list_append(add_list, temp_char);
+			}
+			list_iterator_reset(coord_itr);
+		}
+
+		list_iterator_destroy(char_itr);
+		list_iterator_destroy(coord_itr);
+
+		if(list_count(add_list)) {
+			notice_thread_init();
+			rc = acct_storage_g_add_coord(db_conn, my_uid, 
+						      add_list,
+						      &user_cond);
+			notice_thread_fini();
+			set = 1;
+		}
+		list_destroy(add_list);
+	}
+	list_destroy(user_cond.user_list);
+
+	return set;
+}
+
+static int _mod_assoc(sacctmgr_file_opts_t *file_opts,
+		      acct_association_rec_t *assoc,
+		      sacctmgr_mod_type_t mod_type)
+{
+	int changed = 0;
+	acct_association_rec_t mod_assoc;
+	acct_association_cond_t assoc_cond;
+	char *type = NULL;
+	char *name = NULL;
+	char *my_info = NULL;
+
+	switch(mod_type) {
+	case MOD_CLUSTER:
+		type = "Cluster";
+		name = assoc->cluster;
+		break;
+	case MOD_ACCT:
+		type = "Account";
+		name = assoc->acct;
+		break;
+	case MOD_USER:
+		type = "User";
+		name = assoc->user;
+		break;
+	default:
+		return 0;
+		break;
+	}
+
+	memset(&mod_assoc, 0, sizeof(acct_association_rec_t));
+
+	mod_assoc.fairshare = NO_VAL;
+	mod_assoc.max_cpu_secs_per_job = NO_VAL;
+	mod_assoc.max_jobs = NO_VAL;
+	mod_assoc.max_nodes_per_job = NO_VAL;
+	mod_assoc.max_wall_duration_per_job = NO_VAL;
+
+	memset(&assoc_cond, 0, sizeof(acct_association_cond_t));
+
+	assoc_cond.fairshare = NO_VAL;
+	assoc_cond.max_cpu_secs_per_job = NO_VAL;
+	assoc_cond.max_jobs = NO_VAL;
+	assoc_cond.max_nodes_per_job = NO_VAL;
+	assoc_cond.max_wall_duration_per_job = NO_VAL;
+
+	if(assoc->fairshare != file_opts->fairshare) {
+		mod_assoc.fairshare = file_opts->fairshare;
+		changed = 1;
+		xstrfmtcat(my_info, 
+			   " Changed fairshare for %s '%s' from %d to %d\n",
+			   type, name,
+			   assoc->fairshare,
+			   file_opts->fairshare);
+	}
+	if(assoc->max_cpu_secs_per_job != file_opts->max_cpu_secs_per_job) {
+		mod_assoc.max_cpu_secs_per_job =
+			file_opts->max_cpu_secs_per_job;
+		changed = 1;
+		xstrfmtcat(my_info, 
+			   " Changed MaxCPUSecsPerJob for %s "
+			   "'%s' from %d to %d\n",
+			   type, name,
+			   assoc->max_cpu_secs_per_job,
+			   file_opts->max_cpu_secs_per_job);
+	}
+	if(assoc->max_jobs != file_opts->max_jobs) {
+		mod_assoc.max_jobs = file_opts->max_jobs;
+		changed = 1;
+		xstrfmtcat(my_info, 
+			   " Changed MaxJobs for %s '%s' from %d to %d\n",
+			   type, name,
+			   assoc->max_jobs,
+			   file_opts->max_jobs);
+	}
+	if(assoc->max_nodes_per_job != file_opts->max_nodes_per_job) {
+		mod_assoc.max_nodes_per_job = file_opts->max_nodes_per_job;
+		changed = 1;
+		xstrfmtcat(my_info, 
+			   " Changed MaxNodesPerJob for %s '%s' "
+			   "from %d to %d\n",
+			   type, name,
+			   assoc->max_nodes_per_job, 
+			   file_opts->max_nodes_per_job);
+	}
+	if(assoc->max_wall_duration_per_job !=
+	   file_opts->max_wall_duration_per_job) {
+		mod_assoc.max_wall_duration_per_job =
+			file_opts->max_wall_duration_per_job;
+		changed = 1;
+		xstrfmtcat(my_info, 
+			   " Changed MaxWallDurationPerJob for %s '%s' "
+			   "from %d to %d\n",
+			   type, name,
+			   assoc->max_wall_duration_per_job,
+			   file_opts->max_wall_duration_per_job);
+	}
+
+	if(changed) {
+		List ret_list = NULL;
+					
+		assoc_cond.cluster_list = list_create(NULL); 
+		list_push(assoc_cond.cluster_list, assoc->cluster);
+
+		if(mod_type >= MOD_ACCT) {
+			assoc_cond.acct_list = list_create(NULL); 
+			list_push(assoc_cond.acct_list, assoc->acct);
+		}
+
+		if(mod_type == MOD_USER) {
+			assoc_cond.user_list = list_create(NULL); 
+			list_push(assoc_cond.user_list, assoc->user);
+			if(assoc->partition) {
+				assoc_cond.partition_list = list_create(NULL); 
+				list_push(assoc_cond.partition_list,
+					  assoc->partition);
+			}
+		}
+			
+		notice_thread_init();
+		ret_list = acct_storage_g_modify_associations(
+			db_conn, my_uid,
+			&assoc_cond, 
+			&mod_assoc);
+		notice_thread_fini();
+					
+		list_destroy(assoc_cond.cluster_list);
+		list_destroy(assoc_cond.acct_list);
+		if(assoc_cond.user_list)
+			list_destroy(assoc_cond.user_list);
+		if(assoc_cond.partition_list)
+			list_destroy(assoc_cond.partition_list);
+
+/* 		if(ret_list && list_count(ret_list)) { */
+/* 			char *object = NULL; */
+/* 			ListIterator itr = list_iterator_create(ret_list); */
+/* 			printf(" Modified account defaults for " */
+/* 			       "associations...\n"); */
+/* 			while((object = list_next(itr)))  */
+/* 				printf("  %s\n", object); */
+/* 			list_iterator_destroy(itr); */
+/* 		} */
+ 
+		if(ret_list) {
+			printf("%s", my_info);
+			list_destroy(ret_list);
+		} else
+			changed = 0;
+		xfree(my_info);
+	}
+
+	return changed;
+}
+
+
+static int _print_file_sacctmgr_assoc_childern(FILE *fd, 
+					       List sacctmgr_assoc_list,
+					       List user_list,
+					       List acct_list)
+{
+	ListIterator itr = NULL;
+	sacctmgr_assoc_t *sacctmgr_assoc = NULL;
+	char *line = NULL;
+	acct_user_rec_t *user_rec = NULL;
+	acct_account_rec_t *acct_rec = NULL;
+
+	itr = list_iterator_create(sacctmgr_assoc_list);
+	while((sacctmgr_assoc = list_next(itr))) {
+		if(sacctmgr_assoc->assoc->user) {
+			user_rec = sacctmgr_find_user_from_list(
+				user_list, sacctmgr_assoc->assoc->user);
+			line = xstrdup_printf(
+				"User - %s", sacctmgr_assoc->sort_name);
+			if(user_rec) {
+				xstrfmtcat(line, ":DefaultAccount=%s",
+					   user_rec->default_acct);
+				if(user_rec->admin_level > ACCT_ADMIN_NONE)
+					xstrfmtcat(line, ":AdminLevel=%s",
+						   acct_admin_level_str(
+							   user_rec->
+							   admin_level));
+				if(user_rec->qos > ACCT_QOS_NORMAL)
+					xstrfmtcat(line, ":QOS=%s",
+						   acct_qos_str(user_rec->qos));
+				if(user_rec->coord_accts
+				   && list_count(user_rec->coord_accts)) {
+					ListIterator itr2 = NULL;
+					acct_coord_rec_t *coord = NULL;
+					int first_coord = 1;
+					list_sort(user_rec->coord_accts,
+						  (ListCmpF)sort_coord_list);
+					itr2 = list_iterator_create(
+						user_rec->coord_accts);
+					while((coord = list_next(itr2))) {
+						/* We only care about
+						 * the direct accounts here
+						 */
+						if(!coord->direct) 
+							continue;
+						if(first_coord) {
+							xstrfmtcat(
+								line,
+								":Coordinator"
+								"=%s",
+								coord->name);
+							first_coord = 0;
+						} else {
+							xstrfmtcat(line, ",%s",
+								   coord->name);
+						}				
+					}
+					list_iterator_destroy(itr2);
+				}
+			}
+		} else {
+			acct_rec = sacctmgr_find_account_from_list(
+				acct_list, sacctmgr_assoc->assoc->acct);
+			line = xstrdup_printf(
+				"Account - %s", sacctmgr_assoc->sort_name);
+			if(acct_rec) {
+				xstrfmtcat(line, ":Description='%s'",
+					   acct_rec->description);
+				xstrfmtcat(line, ":Organization='%s'",
+					   acct_rec->organization);
+				if(acct_rec->qos > ACCT_QOS_NORMAL)
+					xstrfmtcat(line, ":QOS=%s",
+						   acct_qos_str(acct_rec->qos));
+			}
+		}
+		if(sacctmgr_assoc->assoc->partition) 
+			xstrfmtcat(line, ":Partition='%s'", 
+				   sacctmgr_assoc->assoc->partition);
+			
+		if(sacctmgr_assoc->assoc->fairshare != INFINITE)
+			xstrfmtcat(line, ":Fairshare=%u", 
+				   sacctmgr_assoc->assoc->fairshare);
+		
+		if(sacctmgr_assoc->assoc->max_cpu_secs_per_job != INFINITE)
+			xstrfmtcat(line, ":MaxCPUSecs=%u",
+				   sacctmgr_assoc->assoc->max_cpu_secs_per_job);
+		
+		if(sacctmgr_assoc->assoc->max_jobs != INFINITE) 
+			xstrfmtcat(line, ":MaxJobs=%u",
+				   sacctmgr_assoc->assoc->max_jobs);
+		
+		if(sacctmgr_assoc->assoc->max_nodes_per_job != INFINITE)
+			xstrfmtcat(line, ":MaxNodes=%u",
+				   sacctmgr_assoc->assoc->max_nodes_per_job);
+		
+		if(sacctmgr_assoc->assoc->max_wall_duration_per_job 
+		   != INFINITE)
+ 			xstrfmtcat(line, ":MaxWallDurationPerJob=%u",
+				   sacctmgr_assoc->assoc->
+				   max_wall_duration_per_job);
+
+
+		if(fprintf(fd, "%s\n", line) < 0) {
+			error("Can't write to file");
+			return SLURM_ERROR;
+		}
+		info("%s", line);
+	}
+	list_iterator_destroy(itr);
+	print_file_sacctmgr_assoc_list(fd, sacctmgr_assoc_list,
+				       user_list, acct_list);
+
+	return SLURM_SUCCESS;
+}
+
+extern int print_file_sacctmgr_assoc_list(FILE *fd, 
+					  List sacctmgr_assoc_list,
+					  List user_list,
+					  List acct_list)
+{
+	ListIterator itr = NULL;
+	sacctmgr_assoc_t *sacctmgr_assoc = NULL;
+
+	itr = list_iterator_create(sacctmgr_assoc_list);
+	while((sacctmgr_assoc = list_next(itr))) {
+/* 		info("got here %d with %d from %s %s",  */
+/* 		     depth, list_count(sacctmgr_assoc->childern), */
+/* 		     sacctmgr_assoc->assoc->acct, sacctmgr_assoc->assoc->user); */
+		if(!list_count(sacctmgr_assoc->childern))
+			continue;
+		if(fprintf(fd, "Parent - %s\n",
+			   sacctmgr_assoc->assoc->acct) < 0) {
+			error("Can't write to file");
+			return SLURM_ERROR;
+		}
+		info("%s - %s", "Parent",
+		       sacctmgr_assoc->assoc->acct);
+/* 		info("sending %d from %s", */
+/* 		     list_count(sacctmgr_assoc->childern), */
+/* 		     sacctmgr_assoc->assoc->acct); */
+		_print_file_sacctmgr_assoc_childern(
+			fd, sacctmgr_assoc->childern, user_list, acct_list);
+	}	
+	list_iterator_destroy(itr);
+
+	return SLURM_SUCCESS;
+}
+
+extern void load_sacctmgr_cfg_file (int argc, char *argv[])
+{
+	DEF_TIMERS;
+	char line[BUFFER_SIZE];
+	FILE *fd = NULL;
+	char *parent = NULL;
+	char *cluster_name = NULL;
+	char object[25];
+	int start = 0, len = 0, i = 0;
+	int lc=0, num_lines=0;
+	int rc = SLURM_SUCCESS;
+
+	sacctmgr_file_opts_t *file_opts = NULL;
+	acct_association_rec_t *assoc = NULL, *assoc2 = NULL;
+	acct_account_rec_t *acct = NULL, *acct2 = NULL;
+	acct_cluster_rec_t *cluster = NULL;
+	acct_user_rec_t *user = NULL, *user2 = NULL;
+	acct_user_cond_t user_cond;
+
+	List curr_assoc_list = NULL;
+	List curr_acct_list = NULL;
+	List curr_cluster_list = NULL;
+	List curr_user_list = NULL;
+
+	/* This will be freed in their local counter parts */
+	List mod_acct_list = NULL;
+	List acct_list = NULL;
+	List acct_assoc_list = NULL;
+	List mod_user_list = NULL;
+	List user_list = NULL;
+	List user_assoc_list = NULL;
+	List mod_assoc_list = NULL;
+
+	ListIterator itr;
+	ListIterator itr2;
+
+	List print_fields_list;
+	List format_list = NULL;
+	print_field_t *field = NULL;
+	
+	int set = 0;
+	
+	fd = fopen(argv[0], "r");
+	if (fd == NULL) {
+		printf(" error: Unable to read \"%s\": %m\n", argv[0]);
+		return;
+	}
+
+	curr_acct_list = acct_storage_g_get_accounts(db_conn, NULL);
+	curr_cluster_list = acct_storage_g_get_clusters(db_conn, NULL);
+
+	memset(&user_cond, 0, sizeof(acct_user_cond_t));
+	user_cond.with_coords = 1;
+	curr_user_list = acct_storage_g_get_users(db_conn, &user_cond);
+
+	/* This will be freed in their local counter parts */
+	acct_list = list_create(NULL);
+	acct_assoc_list = list_create(NULL);
+	user_list = list_create(NULL);
+	user_assoc_list = list_create(NULL);
+	
+	/* These are new info so they need to be freed here */
+	mod_acct_list = list_create(destroy_acct_account_rec);
+	mod_user_list = list_create(destroy_acct_user_rec);
+	mod_assoc_list = list_create(destroy_acct_association_rec);
+
+	format_list = list_create(slurm_destroy_char);
+	
+
+	while((num_lines = _get_next_line(line, BUFFER_SIZE, fd)) > 0) {
+		lc += num_lines;
+		/* skip empty lines */
+		if (line[0] == '\0') {
+			continue;
+		}
+		len = strlen(line);
+
+		memset(object, 0, sizeof(object));
+
+		/* first find the object */
+		start=0;
+		for(i=0; i<len; i++) {
+			if(line[i] == '-') {
+				start = i;
+				if(line[i-1] == ' ') 
+					i--;
+				if(i<sizeof(object))
+					strncpy(object, line, i);
+				break;
+			} 
+		}
+		if(!object[0]) {
+			printf(" error: Misformatted line(%d): %s\n", lc, line);
+			rc = SLURM_ERROR;
+			break;
+		} 
+		while(line[start] != ' ' && start<len)
+			start++;
+		if(start>=len) {
+			printf(" error: Nothing after object "
+			       "name '%s'. line(%d)\n",
+			       object, lc);
+			rc = SLURM_ERROR;
+			break;
+			
+		}
+		start++;
+		
+		if(!strcasecmp("Machine", object) 
+		   || !strcasecmp("Cluster", object)) {
+			acct_association_cond_t assoc_cond;
+
+			if(cluster_name) {
+				printf(" You can only add one cluster "
+				       "at a time.\n");
+				rc = SLURM_ERROR;
+				break;
+			}
+
+			file_opts = _parse_options(line+start);
+			
+			if(!file_opts) {
+				printf(" error: Problem with line(%d)\n", lc);
+				rc = SLURM_ERROR;
+				break;
+			}
+			cluster_name = xstrdup(file_opts->name);
+
+			if(cluster_name)
+				info("For cluster %s", cluster_name);
+
+			if(!(cluster = sacctmgr_find_cluster_from_list(
+				     curr_cluster_list, cluster_name))) {
+				List cluster_list =
+					list_create(destroy_acct_cluster_rec);
+				cluster = xmalloc(sizeof(acct_cluster_rec_t));
+				list_append(cluster_list, cluster);
+				cluster->name = xstrdup(cluster_name);
+				cluster->default_fairshare =
+					file_opts->fairshare;		
+				cluster->default_max_cpu_secs_per_job = 
+					file_opts->max_cpu_secs_per_job;
+				cluster->default_max_jobs = file_opts->max_jobs;
+				cluster->default_max_nodes_per_job = 
+					file_opts->max_nodes_per_job;
+				cluster->default_max_wall_duration_per_job = 
+					file_opts->max_wall_duration_per_job;
+				notice_thread_init();
+				rc = acct_storage_g_add_clusters(
+					db_conn, my_uid, cluster_list);
+				notice_thread_fini();
+				list_destroy(cluster_list);
+
+				if(rc != SLURM_SUCCESS) {
+					printf(" Problem adding machine\n");
+					rc = SLURM_ERROR;
+					break;
+				}
+				set = 1;
+			} else {
+				set = _mod_cluster(file_opts, cluster);
+			}
+				     
+			_destroy_sacctmgr_file_opts(file_opts);
+			
+			memset(&assoc_cond, 0, sizeof(acct_association_cond_t));
+			assoc_cond.cluster_list = list_create(NULL);
+			list_append(assoc_cond.cluster_list, cluster_name);
+			curr_assoc_list = acct_storage_g_get_associations(
+				db_conn, &assoc_cond);
+			list_destroy(assoc_cond.cluster_list);
+
+			if(!curr_assoc_list) {
+				printf(" Problem getting associations "
+				       "for this cluster\n");
+				rc = SLURM_ERROR;
+				break;
+			}
+			//info("got %d assocs", list_count(curr_assoc_list));
+			continue;
+		} else if(!cluster_name) {
+			printf(" error: You need to specify a cluster name "
+			       "first with 'Cluster - $NAME' in your file\n");
+			break;
+		}
+		
+		if(!strcasecmp("Parent", object)) {
+			xfree(parent);
+			
+			i = start;
+			while(line[i] != '\n' && i<len)
+				i++;
+			
+			if(i >= len) {
+				printf(" error: No parent name "
+				       "given line(%d)\n",
+				       lc);
+				rc = SLURM_ERROR;
+				break;
+			}
+			parent = xstrndup(line+start, i-start);
+			//info("got parent %s", parent);
+			if(!sacctmgr_find_account_base_assoc_from_list(
+				   curr_assoc_list, parent, cluster_name)
+			   && !sacctmgr_find_account_base_assoc_from_list(
+				   acct_assoc_list, parent, cluster_name)) {
+				printf(" error: line(%d) You need to add "
+				       "this parent (%s) as a child before "
+				       "you can add childern to it.\n",
+				       lc, parent);
+				break;
+			}
+			continue;
+		} else if(!parent) {
+			parent = xstrdup("root");
+			printf(" No parent given creating off root, "
+			       "If incorrect specify 'Parent - name' "
+			       "before any childern in your file\n");
+		} 
+	
+		if(!strcasecmp("Project", object)
+		   || !strcasecmp("Account", object)) {
+			file_opts = _parse_options(line+start);
+			
+			if(!file_opts) {
+				printf(" error: Problem with line(%d)\n", lc);
+				rc = SLURM_ERROR;
+				break;
+			}
+			
+			//info("got a project %s of %s", file_opts->name, parent);
+			if(!(acct = sacctmgr_find_account_from_list(
+				     curr_acct_list, file_opts->name))
+			   && !sacctmgr_find_account_from_list(
+				   acct_list, file_opts->name)) {
+				acct = xmalloc(sizeof(acct_account_rec_t));
+				acct->assoc_list = NULL;	
+				acct->name = xstrdup(file_opts->name);
+				if(file_opts->desc) 
+					acct->description =
+						xstrdup(file_opts->desc);
+				else
+					acct->description = 
+						xstrdup(file_opts->name);
+				if(file_opts->org)
+					acct->organization =
+						xstrdup(file_opts->org);
+				else if(strcmp(parent, "root"))
+					acct->organization = xstrdup(parent);
+				else
+					acct->organization =
+						xstrdup(file_opts->name);
+				/* info("adding acct %s (%s) (%s)", */
+/* 				     acct->name, acct->description, */
+/* 				     acct->organization); */
+				acct->qos = file_opts->qos;
+				list_append(acct_list, acct);
+				list_append(curr_acct_list, acct);
+
+				assoc = xmalloc(sizeof(acct_association_rec_t));
+				assoc->acct = xstrdup(file_opts->name);
+				assoc->cluster = xstrdup(cluster_name);
+				assoc->parent_acct = xstrdup(parent);
+				assoc->fairshare = file_opts->fairshare;
+				assoc->max_jobs = file_opts->max_jobs;
+				assoc->max_nodes_per_job =
+					file_opts->max_nodes_per_job;
+				assoc->max_wall_duration_per_job =
+					file_opts->max_wall_duration_per_job;
+				assoc->max_cpu_secs_per_job = 
+					file_opts->max_cpu_secs_per_job;
+				list_append(acct_assoc_list, assoc);
+				/* don't add anything to the
+				   curr_assoc_list */
+			} else if(!(assoc =
+				    sacctmgr_find_account_base_assoc_from_list(
+					    curr_assoc_list, file_opts->name,
+					    cluster_name)) &&
+				  !sacctmgr_find_account_base_assoc_from_list(
+					  acct_assoc_list, file_opts->name,
+					  cluster_name)) {
+
+				acct2 = sacctmgr_find_account_from_list(
+					mod_acct_list, file_opts->name);
+
+				if(!acct2) {
+					acct2 = xmalloc(
+						sizeof(acct_account_rec_t));
+					list_append(mod_acct_list, acct2);
+					acct2->name = xstrdup(file_opts->name);
+					if(_mod_acct(file_opts, acct, parent))
+						set = 1;
+				} else {
+					debug2("already modified this account");
+				}
+				assoc = xmalloc(sizeof(acct_association_rec_t));
+				assoc->acct = xstrdup(file_opts->name);
+				assoc->cluster = xstrdup(cluster_name);
+				assoc->parent_acct = xstrdup(parent);
+				assoc->fairshare = file_opts->fairshare;
+				assoc->max_jobs = file_opts->max_jobs;
+				assoc->max_nodes_per_job =
+					file_opts->max_nodes_per_job;
+				assoc->max_wall_duration_per_job =
+					file_opts->max_wall_duration_per_job;
+				assoc->max_cpu_secs_per_job = 
+					file_opts->max_cpu_secs_per_job;
+				list_append(acct_assoc_list, assoc);
+				/* don't add anything to the
+				   curr_assoc_list */
+			} else if(assoc) {
+				acct2 = sacctmgr_find_account_from_list(
+					mod_acct_list, file_opts->name);
+
+				if(!acct2) {
+					acct2 = xmalloc(
+						sizeof(acct_account_rec_t));
+					list_append(mod_acct_list, acct2);
+					acct2->name = xstrdup(file_opts->name);
+					if(_mod_acct(file_opts, acct, parent))
+						set = 1;
+				} else {
+					debug2("already modified this account");
+				}
+				assoc2 = sacctmgr_find_association_from_list(
+					mod_assoc_list,
+					NULL, file_opts->name,
+					cluster_name,
+					NULL);
+
+				if(!assoc2) {
+					assoc2 = xmalloc(
+						sizeof(acct_association_rec_t));
+					list_append(mod_assoc_list, assoc2);
+					assoc2->cluster = xstrdup(cluster_name);
+					assoc2->acct = xstrdup(file_opts->name);
+					if(_mod_assoc(file_opts, 
+						      assoc, MOD_ACCT))
+						set = 1;
+				} else {
+					debug2("already modified this assoc");
+				}
+			}
+			_destroy_sacctmgr_file_opts(file_opts);
+			continue;
+		} else if(!strcasecmp("User", object)) {
+			file_opts = _parse_options(line+start);
+			
+			if(!file_opts) {
+				printf(" error: Problem with line(%d)\n", lc);
+				rc = SLURM_ERROR;
+				break;
+			}
+			if(!(user = sacctmgr_find_user_from_list(
+				     curr_user_list, file_opts->name))
+			   && !sacctmgr_find_user_from_list(
+				   user_list, file_opts->name)) {
+				user = xmalloc(sizeof(acct_user_rec_t));
+				user->assoc_list = NULL;
+				user->name = xstrdup(file_opts->name);
+				if(file_opts->def_acct)
+					user->default_acct = 
+						xstrdup(file_opts->def_acct);
+				else
+					user->default_acct = xstrdup(parent);
+					
+				user->qos = file_opts->qos;
+				user->admin_level = file_opts->admin;
+				
+				if(file_opts->coord_list) {
+					acct_user_cond_t user_cond;
+					ListIterator coord_itr = NULL;
+					char *temp_char = NULL;
+					acct_coord_rec_t *coord = NULL;
+
+					memset(&user_cond, 0,
+					       sizeof(acct_user_cond_t));
+					user_cond.user_list = 
+						list_create(NULL); 
+					
+					list_push(user_cond.user_list,
+						  user->name);
+					
+					notice_thread_init();
+					rc = acct_storage_g_add_coord(
+						db_conn, my_uid, 
+						file_opts->coord_list,
+						&user_cond);
+					notice_thread_fini();
+					list_destroy(user_cond.user_list);
+					user->coord_accts = list_create(
+						destroy_acct_coord_rec);
+					coord_itr = list_iterator_create(
+						file_opts->coord_list);
+					while((temp_char =
+					       list_next(coord_itr))) {
+						coord = xmalloc(
+							sizeof
+							(acct_coord_rec_t));
+						coord->name =
+							xstrdup(temp_char);
+						coord->direct = 1;
+						list_push(user->coord_accts,
+							  coord);
+					}
+					list_iterator_destroy(coord_itr);
+				}
+				
+				list_append(user_list, user);
+				/* don't add anything to the
+				   curr_user_list */
+
+				assoc = xmalloc(sizeof(acct_association_rec_t));
+				assoc->acct = xstrdup(parent);
+				assoc->cluster = xstrdup(cluster_name);
+				assoc->fairshare = file_opts->fairshare;
+				assoc->max_jobs = file_opts->max_jobs;
+				assoc->max_nodes_per_job =
+					file_opts->max_nodes_per_job;
+				assoc->max_wall_duration_per_job =
+					file_opts->max_wall_duration_per_job;
+				assoc->max_cpu_secs_per_job = 
+					file_opts->max_cpu_secs_per_job;
+				assoc->partition = xstrdup(file_opts->part);
+				assoc->user = xstrdup(file_opts->name);
+				
+				list_append(user_assoc_list, assoc);
+				/* don't add anything to the
+				   curr_assoc_list */
+			} else if(!(assoc = sacctmgr_find_association_from_list(
+					    curr_assoc_list,
+					    file_opts->name, parent,
+					    cluster_name, file_opts->part)) 
+				  && !sacctmgr_find_association_from_list(
+					  user_assoc_list,
+					  file_opts->name, parent,
+					  cluster_name,
+					  file_opts->part)) {
+				user2 = sacctmgr_find_user_from_list(
+					mod_user_list, file_opts->name);
+				if(!user2) {
+					user2 = xmalloc(
+						sizeof(acct_user_rec_t));
+					list_append(mod_user_list, user2);
+					user2->name = xstrdup(file_opts->name);
+					if(_mod_user(file_opts, user, parent))
+						set = 1;
+				} else {
+					debug2("already modified this user");
+				}
+
+				assoc = xmalloc(sizeof(acct_association_rec_t));
+				assoc->acct = xstrdup(parent);
+				assoc->cluster = xstrdup(cluster_name);
+				assoc->fairshare = file_opts->fairshare;
+				assoc->max_jobs = file_opts->max_jobs;
+				assoc->max_nodes_per_job =
+					file_opts->max_nodes_per_job;
+				assoc->max_wall_duration_per_job =
+					file_opts->max_wall_duration_per_job;
+				assoc->max_cpu_secs_per_job = 
+					file_opts->max_cpu_secs_per_job;
+				assoc->partition = xstrdup(file_opts->part);
+				assoc->user = xstrdup(file_opts->name);
+				
+				list_append(user_assoc_list, assoc);
+				/* don't add anything to the
+				   curr_assoc_list */
+			} else if(assoc) {
+				user2 = sacctmgr_find_user_from_list(
+					mod_user_list, file_opts->name);
+				if(!user2) {
+					user2 = xmalloc(
+						sizeof(acct_user_rec_t));
+					list_append(mod_user_list, user2);
+					user2->name = xstrdup(file_opts->name);
+					if(_mod_user(file_opts, user, parent))
+						set = 1;
+				} else {
+					debug2("already modified this user");
+				}
+
+				assoc2 = sacctmgr_find_association_from_list(
+					mod_assoc_list,
+					file_opts->name, parent,
+					cluster_name,
+					file_opts->part);
+
+				if(!assoc2) {
+					assoc2 = xmalloc(
+						sizeof(acct_association_rec_t));
+					list_append(mod_assoc_list, assoc2);
+					assoc2->cluster = xstrdup(cluster_name);
+					assoc2->acct = xstrdup(parent);
+					assoc2->user = xstrdup(file_opts->name);
+					assoc2->partition =
+						xstrdup(file_opts->part);
+					if(_mod_assoc(file_opts, 
+						      assoc, MOD_USER))
+						set = 1;
+				} else {
+					debug2("already modified this assoc");
+				}
+			}
+			//info("got a user %s", file_opts->name);
+			_destroy_sacctmgr_file_opts(file_opts);
+			continue;
+		} else {
+			printf(" error: Misformatted line(%d): %s\n", lc, line);
+			rc = SLURM_ERROR;
+			break;
+		}
+	}
+	fclose(fd);
+	xfree(cluster_name);
+	xfree(parent);
+		
+	START_TIMER;
+	if(rc == SLURM_SUCCESS && list_count(acct_list)) {
+		printf("Accounts\n");
+		addto_char_list(format_list,
+				"Name,Description,Organization,QOS");
+
+		print_fields_list = _set_up_print_fields(format_list);
+		list_flush(format_list);
+		
+		print_fields_header(print_fields_list);
+
+		itr = list_iterator_create(acct_list);
+		itr2 = list_iterator_create(print_fields_list);
+		while((acct = list_next(itr))) {
+			while((field = list_next(itr2))) {
+				switch(field->type) {
+				case PRINT_DESC:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field, acct->description);
+					break;
+				case PRINT_NAME:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field, acct->name);
+					break;
+				case PRINT_ORG:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field, acct->organization);
+					break;
+				case PRINT_QOS:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						acct_qos_str(acct->qos));
+					break;
+				default:
+					break;
+				}
+			}
+			list_iterator_reset(itr2);
+			printf("\n");
+		}
+		list_iterator_destroy(itr);
+		list_iterator_destroy(itr2);
+		list_destroy(print_fields_list);
+		rc = acct_storage_g_add_accounts(db_conn, my_uid, acct_list);
+		printf("-----------------------------"
+		       "----------------------\n\n");
+		set = 1;
+	}
+	
+	if(rc == SLURM_SUCCESS && list_count(acct_assoc_list)) {
+		printf("Account Associations\n");
+		_print_out_assoc(acct_assoc_list, 0);
+		set = 1;
+	}
+	if(rc == SLURM_SUCCESS && list_count(user_list)) {
+		printf("Users\n");
+
+		addto_char_list(format_list, "Name,Default,QOS,Admin,Coord");
+
+		print_fields_list = _set_up_print_fields(format_list);
+		list_flush(format_list);
+		print_fields_header(print_fields_list);
+
+		itr = list_iterator_create(user_list);
+		itr2 = list_iterator_create(print_fields_list);
+		while((user = list_next(itr))) {
+			while((field = list_next(itr2))) {
+				switch(field->type) {
+				case PRINT_ADMIN:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						acct_admin_level_str(
+							user->admin_level));
+					break;
+				case PRINT_COORDS:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field,
+						user->coord_accts);
+					break;
+				case PRINT_DACCT:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						user->default_acct);
+					break;
+				case PRINT_NAME:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field, user->name);
+					break;
+				case PRINT_QOS:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						acct_qos_str(user->qos));
+					break;
+				default:
+					break;
+				}
+			}
+			list_iterator_reset(itr2);
+			printf("\n");
+		}
+		list_iterator_destroy(itr);
+		list_iterator_destroy(itr2);
+		list_destroy(print_fields_list);
+		
+		rc = acct_storage_g_add_users(db_conn, my_uid, user_list);
+		printf("---------------------------"
+		       "------------------------\n\n");
+		set = 1;
+	}
+	
+	if(rc == SLURM_SUCCESS && list_count(user_assoc_list)) {
+		printf("User Associations\n");
+		_print_out_assoc(user_assoc_list, 1);
+		set = 1;
+	}
+	END_TIMER2("add cluster");
+		
+	info("Done adding cluster in %s", TIME_STR);
+		
+	if(rc == SLURM_SUCCESS) {
+		if(set) {
+			if(commit_check("Would you like to commit changes?")) {
+				acct_storage_g_commit(db_conn, 1);
+			} else {
+				printf(" Changes Discarded\n");
+				acct_storage_g_commit(db_conn, 0);
+			}
+		} else {
+			printf(" Nothing new added.\n");
+		}
+	} else {
+		printf(" error: Problem with requests.\n");
+	}
+
+	list_destroy(format_list);
+	list_destroy(acct_list);
+	list_destroy(acct_assoc_list);
+	list_destroy(user_list);
+	list_destroy(user_assoc_list);
+	if(curr_acct_list)
+		list_destroy(curr_acct_list);
+	if(curr_assoc_list)
+		list_destroy(curr_assoc_list);
+	if(curr_cluster_list)
+		list_destroy(curr_cluster_list);
+	if(curr_user_list)
+		list_destroy(curr_user_list);
+}
diff --git a/src/sacctmgr/sacctmgr.c b/src/sacctmgr/sacctmgr.c
index b19eebb2fb04b10441706ea2ecc73d8864a2917d..cbdc03aa6b8404addb422d241abf737c797c7131 100644
--- a/src/sacctmgr/sacctmgr.c
+++ b/src/sacctmgr/sacctmgr.c
@@ -44,22 +44,6 @@
 #define OPT_LONG_HIDE   0x102
 #define BUFFER_SIZE 4096
 
-typedef struct {
-	uint16_t admin;
-	char *def_acct;
-	char *desc;
-	uint32_t fairshare;
-	uint32_t max_cpu_secs_per_job; 
-	uint32_t max_jobs;
-	uint32_t max_nodes_per_job; 
-	uint32_t max_wall_duration_per_job;
-	char *name;
-	char *org;
-	char *part;
-	uint16_t qos;
-} sacctmgr_file_opts_t;
-
-
 char *command_name;
 int all_flag;		/* display even hidden partitions */
 int exit_code;		/* sacctmgr's exit code, =1 on any error at any time */
@@ -76,7 +60,6 @@ static void	_show_it (int argc, char *argv[]);
 static void	_add_it (int argc, char *argv[]);
 static void	_modify_it (int argc, char *argv[]);
 static void	_delete_it (int argc, char *argv[]);
-static void	_load_file (int argc, char *argv[]);
 static int	_get_command (int *argc, char *argv[]);
 static void     _print_version( void );
 static int	_process_command (int argc, char *argv[]);
@@ -99,6 +82,7 @@ main (int argc, char *argv[])
 		{"no_header", 0, 0, 'n'},
 		{"parsable", 0, 0, 'p'},
 		{"quiet",    0, 0, 'q'},
+		{"associations", 0, 0, 's'},
 		{"usage",    0, 0, 'h'},
 		{"verbose",  0, 0, 'v'},
 		{"version",  0, 0, 'V'},
@@ -326,6 +310,15 @@ _process_command (int argc, char *argv[])
 		all_flag = 1;
 	} else if (strncasecmp (argv[0], "associations", 3) == 0) {
 		with_assoc_flag = 1;
+	} else if (strncasecmp (argv[0], "dump", 3) == 0) {
+		if (argc < 2) {
+			exit_code = 1;
+			if (quiet_flag != 1)
+				fprintf(stderr, 
+				        "too few arguments for keyword:%s\n", 
+				        argv[0]);
+		} else
+			sacctmgr_dump_cluster((argc - 1), &argv[1]);
 	} else if (strncasecmp (argv[0], "help", 2) == 0) {
 		if (argc > 1) {
 			exit_code = 1;
@@ -344,7 +337,7 @@ _process_command (int argc, char *argv[])
 				        "too few arguments for keyword:%s\n", 
 				        argv[0]);
 		} else
-			_load_file((argc - 1), &argv[1]);
+			load_sacctmgr_cfg_file((argc - 1), &argv[1]);
 	} else if (strncasecmp (argv[0], "oneliner", 1) == 0) {
 		if (argc > 1) {
 			exit_code = 1;
@@ -574,829 +567,6 @@ static void _delete_it (int argc, char *argv[])
 	}
 }
 
-static int _strip_continuation(char *buf, int len)
-{
-	char *ptr;
-	int bs = 0;
-
-	for (ptr = buf+len-1; ptr >= buf; ptr--) {
-		if (*ptr == '\\')
-			bs++;
-		else if (isspace(*ptr) && bs == 0)
-			continue;
-		else
-			break;
-	}
-	/* Check for an odd number of contiguous backslashes at
-	   the end of the line */
-	if (bs % 2 == 1) {
-		ptr = ptr + bs;
-		*ptr = '\0';
-		return (ptr - buf);
-	} else {
-		return len; /* no continuation */
-	}
-}
-
-/* Strip comments from a line by terminating the string
- * where the comment begins.
- * Everything after a non-escaped "#" is a comment.
- */
-static void _strip_comments(char *line)
-{
-	int i;
-	int len = strlen(line);
-	int bs_count = 0;
-
-	for (i = 0; i < len; i++) {
-		/* if # character is preceded by an even number of
-		 * escape characters '\' */
-		if (line[i] == '#' && (bs_count%2) == 0) {
-			line[i] = '\0';
- 			break;
-		} else if (line[i] == '\\') {
-			bs_count++;
-		} else {
-			bs_count = 0;
-		}
-	}
-}
-
-/*
- * Strips any escape characters, "\".  If you WANT a back-slash,
- * it must be escaped, "\\".
- */
-static void _strip_escapes(char *line)
-{
-	int i, j;
-	int len = strlen(line);
-
-	for (i = 0, j = 0; i < len+1; i++, j++) {
-		if (line[i] == '\\')
-			i++;
-		line[j] = line[i];
-	}
-}
-
-/*
- * Reads the next line from the "file" into buffer "buf".
- *
- * Concatonates together lines that are continued on
- * the next line by a trailing "\".  Strips out comments,
- * replaces escaped "\#" with "#", and replaces "\\" with "\".
- */
-static int _get_next_line(char *buf, int buf_size, FILE *file)
-{
-	char *ptr = buf;
-	int leftover = buf_size;
-	int read_size, new_size;
-	int lines = 0;
-
-	while (fgets(ptr, leftover, file)) {
-		lines++;
-		_strip_comments(ptr);
-		read_size = strlen(ptr);
-		new_size = _strip_continuation(ptr, read_size);
-		if (new_size < read_size) {
-			ptr += new_size;
-			leftover -= new_size;
-		} else { /* no continuation */
-			break;
-		}
-	}
-	/* _strip_cr_nl(buf); */ /* not necessary */
-	_strip_escapes(buf);
-	
-	return lines;
-}
-
-static void _destroy_sacctmgr_file_opts(void *object)
-{
-	sacctmgr_file_opts_t *file_opts = (sacctmgr_file_opts_t *)object;
-
-	if(file_opts) {
-		xfree(file_opts->def_acct);
-		xfree(file_opts->desc);
-		xfree(file_opts->name);
-		xfree(file_opts->org);
-		xfree(file_opts->part);
-		xfree(file_opts);		
-	}
-}
-
-static sacctmgr_file_opts_t *_parse_options(char *options)
-{
-	int start=0, i=0, end=0, mins, quote = 0;
- 	char *sub = NULL;
-	sacctmgr_file_opts_t *file_opts = xmalloc(sizeof(sacctmgr_file_opts_t));
-	char *option = NULL;
-
-	file_opts->fairshare = NO_VAL;
-	file_opts->max_cpu_secs_per_job = NO_VAL;
-	file_opts->max_jobs = NO_VAL;
-	file_opts->max_nodes_per_job = NO_VAL;
-	file_opts->max_wall_duration_per_job = NO_VAL;
-
-	while(options[i]) {
-		quote = 0;
-		start=i;
-		
-		while(options[i] && options[i] != ':' && options[i] != '\n') {
-			if(options[i] == '"') {
-				if(quote)
-					quote = 0;
-				else
-					quote = 1;
-			}
-			i++;
-		}
-		if(quote) {
-			while(options[i] && options[i] != '"') 
-				i++;
-			if(!options[i])
-				fatal("There is a problem with option "
-				      "%s with quotes.", option);
-			i++;
-		}
-		sub = xstrndup(options+start, i-start);
-		end = parse_option_end(sub);
-		
-		option = strip_quotes(sub+end, NULL);
-		
-		if(!end) {
-			if(file_opts->name) {
-				printf(" Bad format on %s: "
-				       "End your option with "
-				       "an '=' sign\n", sub);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-			file_opts->name = xstrdup(option);
-		} else if (strncasecmp (sub, "AdminLevel", 2) == 0) {
-			file_opts->admin = str_2_acct_admin_level(option);
-		} else if (strncasecmp (sub, "DefaultAccount", 3) == 0) {
-			file_opts->def_acct = xstrdup(option);
-		} else if (strncasecmp (sub, "Description", 3) == 0) {
-			file_opts->desc = xstrdup(option);
-		} else if (strncasecmp (sub, "FairShare", 1) == 0) {
-			if (get_uint(option, &file_opts->fairshare, 
-			    "FairShare") != SLURM_SUCCESS) {
-				printf(" Bad FairShare value: %s\n", option);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-		} else if (strncasecmp (sub, "MaxCPUSec", 4) == 0
-			   || strncasecmp (sub, "MaxProcSec", 4) == 0) {
-			if (get_uint(option, &file_opts->max_cpu_secs_per_job,
-			    "MaxCPUSec") != SLURM_SUCCESS) {
-				printf(" Bad MaxCPUSec value: %s\n", option);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-		} else if (strncasecmp (sub, "MaxJobs", 4) == 0) {
-			if (get_uint(option, &file_opts->max_jobs,
-			    "MaxJobs") != SLURM_SUCCESS) {
-				printf(" Bad MaxJobs value: %s\n", option);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-		} else if (strncasecmp (sub, "MaxNodes", 4) == 0) {
-			if (get_uint(option, &file_opts->max_nodes_per_job,
-			    "MaxNodes") != SLURM_SUCCESS) {
-				printf(" Bad MaxNodes value: %s\n", option);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-		} else if (strncasecmp (sub, "MaxWall", 4) == 0) {
-			mins = time_str2mins(option);
-			if (mins >= 0) {
-				file_opts->max_wall_duration_per_job 
-					= (uint32_t) mins;
-			} else if (strcmp(option, "-1") == 0) {
-				file_opts->max_wall_duration_per_job = -1;
-			} else {
-				printf(" Bad MaxWall time format: %s\n", 
-					option);
-				_destroy_sacctmgr_file_opts(file_opts);
-				break;
-			}
-		} else if (strncasecmp (sub, "Organization", 1) == 0) {
-			file_opts->org = xstrdup(option);
-		} else if (strncasecmp (sub, "QosLevel", 1) == 0
-			   || strncasecmp (sub, "Expedite", 1) == 0) {
-			file_opts->qos = str_2_acct_qos(option);
-		} else {
-			printf(" Unknown option: %s\n", sub);
-		}
-
-		xfree(sub);
-		xfree(option);
-
-		if(options[i] == ':')
-			i++;
-		else
-			break;
-	}
-	
-	xfree(sub);
-	xfree(option);
-
-	if(!file_opts->name) {
-		printf(" error: No name given\n");
-		_destroy_sacctmgr_file_opts(file_opts);
-	}
-	return file_opts;
-}
-
-static void _load_file (int argc, char *argv[])
-{
-	DEF_TIMERS;
-	char line[BUFFER_SIZE];
-	FILE *fd = NULL;
-	char *parent = NULL;
-	char *cluster_name = NULL;
-	char object[25];
-	int start = 0, len = 0, i = 0;
-	int lc=0, num_lines=0;
-	int rc = SLURM_SUCCESS;
-
-	sacctmgr_file_opts_t *file_opts = NULL;
-	acct_association_rec_t *assoc = NULL;
-	acct_account_rec_t *acct = NULL;
-	acct_cluster_rec_t *cluster = NULL;
-	acct_user_rec_t *user = NULL;
-
-	List curr_assoc_list = NULL;
-	List curr_acct_list = acct_storage_g_get_accounts(db_conn, NULL);
-	List curr_cluster_list = acct_storage_g_get_clusters(db_conn, NULL);
-	List curr_user_list = acct_storage_g_get_users(db_conn, NULL);
-
-	/* This will be freed in their local counter parts */
-	List acct_list = list_create(NULL);
-	List acct_assoc_list = list_create(NULL);
-	List user_list = list_create(NULL);
-	List user_assoc_list = list_create(NULL);
-
-	ListIterator itr;
-
-	List print_fields_list;
-
-	print_field_t name_field;
-	print_field_t acct_field;
-	print_field_t parent_field;
-	print_field_t fs_field;
-	print_field_t mc_field;
-	print_field_t mj_field;
-	print_field_t mn_field;
-	print_field_t mw_field;
-
-	print_field_t desc_field;
-	print_field_t org_field;
-	print_field_t qos_field;
-
-	print_field_t admin_field;
-	print_field_t dacct_field;
-	
-	int set = 0;
-	
-	fd = fopen(argv[0], "r");
-	if (fd == NULL) {
-		printf(" error: Unable to read \"%s\": %m\n", argv[0]);
-		return;
-	}
-
-	while((num_lines = _get_next_line(line, BUFFER_SIZE, fd)) > 0) {
-		lc += num_lines;
-		/* skip empty lines */
-		if (line[0] == '\0') {
-			continue;
-		}
-		len = strlen(line);
-
-		memset(object, 0, sizeof(object));
-
-		/* first find the object */
-		start=0;
-		for(i=0; i<len; i++) {
-			if(line[i] == '-') {
-				start = i;
-				if(line[i-1] == ' ') 
-					i--;
-				if(i<sizeof(object))
-					strncpy(object, line, i);
-				break;
-			} 
-		}
-		if(!object[0]) {
-			printf(" error: Misformatted line(%d): %s\n", lc, line);
-			rc = SLURM_ERROR;
-			break;
-		} 
-		while(line[start] != ' ' && start<len)
-			start++;
-		if(start>=len) {
-			printf(" error: Nothing after object "
-			       "name '%s'. line(%d)\n",
-			       object, lc);
-			rc = SLURM_ERROR;
-			break;
-			
-		}
-		start++;
-		
-		if(!strcasecmp("Machine", object) 
-		   || !strcasecmp("Cluster", object)) {
-			acct_association_cond_t assoc_cond;
-
-			if(cluster_name) {
-				printf(" You can only add one cluster "
-				       "at a time.\n");
-				rc = SLURM_ERROR;
-				break;
-			}
-			file_opts = _parse_options(line+start);
-			
-			if(!file_opts) {
-				printf(" error: Problem with line(%d)\n", lc);
-				rc = SLURM_ERROR;
-				break;
-			}
-			cluster_name = xstrdup(file_opts->name);
-			if(!sacctmgr_find_cluster_from_list(
-				   curr_cluster_list, cluster_name)) {
-				List cluster_list =
-					list_create(destroy_acct_cluster_rec);
-				cluster = xmalloc(sizeof(acct_cluster_rec_t));
-				list_append(cluster_list, cluster);
-				cluster->name = xstrdup(cluster_name);
-				cluster->default_fairshare =
-					file_opts->fairshare;		
-				cluster->default_max_cpu_secs_per_job = 
-					file_opts->max_cpu_secs_per_job;
-				cluster->default_max_jobs = file_opts->max_jobs;
-				cluster->default_max_nodes_per_job = 
-					file_opts->max_nodes_per_job;
-				cluster->default_max_wall_duration_per_job = 
-					file_opts->max_wall_duration_per_job;
-				notice_thread_init();
-				rc = acct_storage_g_add_clusters(
-					db_conn, my_uid, cluster_list);
-				notice_thread_fini();
-				list_destroy(cluster_list);
-
-				if(rc != SLURM_SUCCESS) {
-					printf(" Problem adding machine\n");
-					rc = SLURM_ERROR;
-					break;
-				}
-			}
-			info("For cluster %s", cluster_name);
-			_destroy_sacctmgr_file_opts(file_opts);
-			
-			memset(&assoc_cond, 0, sizeof(acct_association_cond_t));
-			assoc_cond.cluster_list = list_create(NULL);
-			list_append(assoc_cond.cluster_list, cluster_name);
-			curr_assoc_list = acct_storage_g_get_associations(
-				db_conn, &assoc_cond);
-			list_destroy(assoc_cond.cluster_list);
-
-			if(!curr_assoc_list) {
-				printf(" Problem getting associations "
-				       "for this cluster\n");
-				rc = SLURM_ERROR;
-				break;
-			}
-			//info("got %d assocs", list_count(curr_assoc_list));
-			continue;
-		} else if(!cluster_name) {
-			printf(" error: You need to specify a cluster name "
-			       "first with 'Cluster - name' in your file\n");
-			break;
-		}
-
-		if(!strcasecmp("Parent", object)) {
-			if(parent) 
-				xfree(parent);
-			
-			i = start;
-			while(line[i] != '\n' && i<len)
-				i++;
-			
-			if(i >= len) {
-				printf(" error: No parent name "
-				       "given line(%d)\n",
-				       lc);
-				rc = SLURM_ERROR;
-				break;
-			}
-			parent = xstrndup(line+start, i-start);
-			//info("got parent %s", parent);
-			if(!sacctmgr_find_account_base_assoc_from_list(
-				   curr_assoc_list, parent, cluster_name)
-			   && !sacctmgr_find_account_base_assoc_from_list(
-				   acct_assoc_list, parent, cluster_name)) {
-				printf(" error: line(%d) You need to add "
-				       "this parent (%s) as a child before "
-				       "you can add childern to it.\n",
-				       lc, parent);
-				break;
-			}
-			continue;
-		} else if(!parent) {
-			parent = xstrdup("root");
-			printf(" No parent given creating off root, "
-			       "If incorrect specify 'Parent - name' "
-			       "before any childern in your file\n");
-		} 
-	
-		if(!strcasecmp("Project", object)
-		   || !strcasecmp("Account", object)) {
-			file_opts = _parse_options(line+start);
-			
-			if(!file_opts) {
-				printf(" error: Problem with line(%d)\n", lc);
-				rc = SLURM_ERROR;
-				break;
-			}
-			
-			//info("got a project %s of %s", file_opts->name, parent);
-			if(!sacctmgr_find_account_from_list(
-				   curr_acct_list, file_opts->name)) {
-				acct = xmalloc(sizeof(acct_account_rec_t));
-				acct->assoc_list = NULL;	
-				acct->name = xstrdup(file_opts->name);
-				if(file_opts->desc) 
-					acct->description =
-						xstrdup(file_opts->desc);
-				else
-					acct->description = 
-						xstrdup(file_opts->name);
-				if(file_opts->org)
-					acct->organization =
-						xstrdup(file_opts->org);
-				else if(strcmp(parent, "root"))
-					acct->organization = xstrdup(parent);
-				else
-					acct->organization =
-						xstrdup(file_opts->name);
-				/* info("adding acct %s (%s) (%s)", */
-/* 				     acct->name, acct->description, */
-/* 				     acct->organization); */
-				acct->qos = file_opts->qos;
-				list_append(acct_list, acct);
-				list_append(curr_acct_list, acct);
-
-				assoc = xmalloc(sizeof(acct_association_rec_t));
-				assoc->acct = xstrdup(file_opts->name);
-				assoc->cluster = xstrdup(cluster_name);
-				assoc->parent_acct = xstrdup(parent);
-				assoc->fairshare = file_opts->fairshare;
-				assoc->max_jobs = file_opts->max_jobs;
-				assoc->max_nodes_per_job =
-					file_opts->max_nodes_per_job;
-				assoc->max_wall_duration_per_job =
-					file_opts->max_wall_duration_per_job;
-				assoc->max_cpu_secs_per_job = 
-					file_opts->max_cpu_secs_per_job;
-				list_append(acct_assoc_list, assoc);
-				/* don't add anything to the
-				   curr_assoc_list */
-			} else if(!sacctmgr_find_account_base_assoc_from_list(
-					  curr_assoc_list, file_opts->name,
-					  cluster_name) &&
-				  !sacctmgr_find_account_base_assoc_from_list(
-					  acct_assoc_list, file_opts->name,
-					  cluster_name)) {
-				assoc = xmalloc(sizeof(acct_association_rec_t));
-				assoc->acct = xstrdup(file_opts->name);
-				assoc->cluster = xstrdup(cluster_name);
-				assoc->parent_acct = xstrdup(parent);
-				assoc->fairshare = file_opts->fairshare;
-				assoc->max_jobs = file_opts->max_jobs;
-				assoc->max_nodes_per_job =
-					file_opts->max_nodes_per_job;
-				assoc->max_wall_duration_per_job =
-					file_opts->max_wall_duration_per_job;
-				assoc->max_cpu_secs_per_job = 
-					file_opts->max_cpu_secs_per_job;
-				list_append(acct_assoc_list, assoc);
-				/* don't add anything to the
-				   curr_assoc_list */
-			}
-			_destroy_sacctmgr_file_opts(file_opts);
-			continue;
-		} else if(!strcasecmp("User", object)) {
-			file_opts = _parse_options(line+start);
-			
-			if(!file_opts) {
-				printf(" error: Problem with line(%d)\n", lc);
-				rc = SLURM_ERROR;
-				break;
-			}
-			if(!sacctmgr_find_user_from_list(
-				   curr_user_list, file_opts->name)
-			   && !sacctmgr_find_user_from_list(
-				   user_list, file_opts->name)) {
-				user = xmalloc(sizeof(acct_user_rec_t));
-				user->assoc_list = NULL;
-				user->name = xstrdup(file_opts->name);
-				if(file_opts->def_acct)
-					user->default_acct = 
-						xstrdup(file_opts->def_acct);
-				else
-					user->default_acct = xstrdup(parent);
-					
-				user->qos = file_opts->qos;
-				user->admin_level = file_opts->admin;
-				
-				list_append(user_list, user);
-				/* don't add anything to the
-				   curr_user_list */
-
-				assoc = xmalloc(sizeof(acct_association_rec_t));
-				assoc->acct = xstrdup(parent);
-				assoc->cluster = xstrdup(cluster_name);
-				assoc->fairshare = file_opts->fairshare;
-				assoc->max_jobs = file_opts->max_jobs;
-				assoc->max_nodes_per_job =
-					file_opts->max_nodes_per_job;
-				assoc->max_wall_duration_per_job =
-					file_opts->max_wall_duration_per_job;
-				assoc->max_cpu_secs_per_job = 
-					file_opts->max_cpu_secs_per_job;
-				assoc->partition = xstrdup(file_opts->part);
-				assoc->user = xstrdup(file_opts->name);
-				
-				list_append(user_assoc_list, assoc);
-				/* don't add anything to the
-				   curr_assoc_list */
-			} else if(!sacctmgr_find_association_from_list(
-					  curr_assoc_list,
-					  file_opts->name, parent,
-					  cluster_name, file_opts->part)
-				&& !sacctmgr_find_association_from_list(
-					  user_assoc_list,
-					  file_opts->name, parent,
-					  cluster_name, file_opts->part)) {
-				assoc = xmalloc(sizeof(acct_association_rec_t));
-				assoc->acct = xstrdup(parent);
-				assoc->cluster = xstrdup(cluster_name);
-				assoc->fairshare = file_opts->fairshare;
-				assoc->max_jobs = file_opts->max_jobs;
-				assoc->max_nodes_per_job =
-					file_opts->max_nodes_per_job;
-				assoc->max_wall_duration_per_job =
-					file_opts->max_wall_duration_per_job;
-				assoc->max_cpu_secs_per_job = 
-					file_opts->max_cpu_secs_per_job;
-				assoc->partition = xstrdup(file_opts->part);
-				assoc->user = xstrdup(file_opts->name);
-				
-				list_append(user_assoc_list, assoc);
-				/* don't add anything to the
-				   curr_assoc_list */
-			}
-			//info("got a user %s", file_opts->name);
-			_destroy_sacctmgr_file_opts(file_opts);
-			continue;
-		} else {
-			printf(" error: Misformatted line(%d): %s\n", lc, line);
-			rc = SLURM_ERROR;
-			break;
-		}
-	}
-	fclose(fd);
-	xfree(cluster_name);
-	xfree(parent);
-
-	admin_field.name = "Admin";
-	admin_field.len = 9;
-	admin_field.print_routine = print_fields_str;
-
-	name_field.name = "Name";
-	name_field.len = 10;
-	name_field.print_routine = print_fields_str;
-		
-	parent_field.name = "Parent";
-	parent_field.len = 10;
-	parent_field.print_routine = print_fields_str;
-	
-	acct_field.name = "Account";
-	acct_field.len = 10;
-	acct_field.print_routine = print_fields_str;
-	
-	dacct_field.name = "Def Acct";
-	dacct_field.len = 10;
-	dacct_field.print_routine = print_fields_str;
-	
-	desc_field.name = "Descr";
-	desc_field.len = 10;
-	desc_field.print_routine = print_fields_str;
-	
-	org_field.name = "Org";
-	org_field.len = 10;
-	org_field.print_routine = print_fields_str;
-	
-	qos_field.name = "QOS";
-	qos_field.len = 9;
-	qos_field.print_routine = print_fields_str;
-	
-	fs_field.name = "FairShare";
-	fs_field.len = 10;
-	fs_field.print_routine = print_fields_uint;
-
-	mc_field.name = "MaxCPUSecs";
-	mc_field.len = 10;
-	mc_field.print_routine = print_fields_uint;
-
-	mj_field.name = "MaxJobs";
-	mj_field.len = 7;
-	mj_field.print_routine = print_fields_uint;
-
-	mn_field.name = "MaxNodes";
-	mn_field.len = 8;
-	mn_field.print_routine = print_fields_uint;
-
-	mw_field.name = "MaxWall";
-	mw_field.len = 7;
-	mw_field.print_routine = print_fields_time;
-		
-	START_TIMER;
-	if(rc == SLURM_SUCCESS && list_count(acct_list)) {
-		printf("Accounts\n");
-
-		print_fields_list = list_create(NULL);
-		list_append(print_fields_list, &name_field);
-		list_append(print_fields_list, &desc_field);
-		list_append(print_fields_list, &org_field);
-		list_append(print_fields_list, &qos_field);
-
-		print_fields_header(print_fields_list);
-
-		itr = list_iterator_create(acct_list);
-		while((acct = list_next(itr))) {
-			print_fields_str(SLURM_PRINT_VALUE, &name_field, 
-				  acct->name);
-			print_fields_str(SLURM_PRINT_VALUE, &desc_field, 
-				  acct->description);
-			print_fields_str(SLURM_PRINT_VALUE, &org_field, 
-				  acct->organization);
-			print_fields_str(SLURM_PRINT_VALUE, &qos_field, 
-				  acct_qos_str(acct->qos));
-			printf("\n");
-		}
-		list_iterator_destroy(itr);
-		list_destroy(print_fields_list);
-		rc = acct_storage_g_add_accounts(db_conn, my_uid, acct_list);
-		printf("---------------------------------------------------\n");
-		set = 1;
-	}
-	
-	if(rc == SLURM_SUCCESS && list_count(acct_assoc_list)) {
-		printf("Account Associations\n");
-
-		print_fields_list = list_create(NULL);
-		list_append(print_fields_list, &name_field);
-		list_append(print_fields_list, &parent_field);
-		list_append(print_fields_list, &fs_field);
-		list_append(print_fields_list, &mc_field);
-		list_append(print_fields_list, &mj_field);
-		list_append(print_fields_list, &mn_field);
-		list_append(print_fields_list, &mw_field);
-
-		print_fields_header(print_fields_list);
-		
-		itr = list_iterator_create(acct_assoc_list);
-		while((assoc = list_next(itr))) {
-			print_fields_str(SLURM_PRINT_VALUE, &name_field,
-					 assoc->acct);
-			print_fields_str(SLURM_PRINT_VALUE, &parent_field, 
-					 assoc->parent_acct);
-			print_fields_uint(SLURM_PRINT_VALUE, &fs_field, 
-					  assoc->fairshare);
-			print_fields_uint(SLURM_PRINT_VALUE, &mc_field, 
-					  assoc->max_cpu_secs_per_job);
-			print_fields_uint(SLURM_PRINT_VALUE, &mj_field, 
-					  assoc->max_jobs);
-			print_fields_uint(SLURM_PRINT_VALUE, &mn_field, 
-					  assoc->max_nodes_per_job);
-			print_fields_time(SLURM_PRINT_VALUE, &mw_field,
-					  assoc->max_wall_duration_per_job);
-			printf("\n");
-		}
-		list_iterator_destroy(itr);
-		list_destroy(print_fields_list);
-		
-		rc = acct_storage_g_add_associations(
-			db_conn, my_uid, acct_assoc_list);
-		printf("---------------------------------------------------\n");
-		set = 1;
-	}
-	if(rc == SLURM_SUCCESS && list_count(user_list)) {
-		printf("Users\n");
-
-		print_fields_list = list_create(NULL);
-		list_append(print_fields_list, &name_field);
-		list_append(print_fields_list, &dacct_field);
-		list_append(print_fields_list, &qos_field);
-		list_append(print_fields_list, &admin_field);
-
-		print_fields_header(print_fields_list);
-
-		itr = list_iterator_create(user_list);
-		while((acct = list_next(itr))) {
-			print_fields_str(SLURM_PRINT_VALUE, &name_field,
-					 user->name);
-			print_fields_str(SLURM_PRINT_VALUE, &dacct_field, 
-					 user->default_acct);
-			print_fields_str(SLURM_PRINT_VALUE, &qos_field, 
-					 acct_qos_str(user->qos));
-			print_fields_str(SLURM_PRINT_VALUE, &admin_field,
-					 acct_admin_level_str(
-						 user->admin_level));
-			printf("\n");
-		}
-		list_iterator_destroy(itr);
-		list_destroy(print_fields_list);
-		
-		rc = acct_storage_g_add_users(db_conn, my_uid, user_list);
-		printf("---------------------------------------------------\n");
-		set = 1;
-	}
-
-	if(rc == SLURM_SUCCESS && list_count(user_assoc_list)) {
-		printf("User Associations\n");
-
-		print_fields_list = list_create(NULL);
-		list_append(print_fields_list, &name_field);
-		list_append(print_fields_list, &acct_field);
-		list_append(print_fields_list, &fs_field);
-		list_append(print_fields_list, &mc_field);
-		list_append(print_fields_list, &mj_field);
-		list_append(print_fields_list, &mn_field);
-		list_append(print_fields_list, &mw_field);
-
-		print_fields_header(print_fields_list);
-		
-		itr = list_iterator_create(user_assoc_list);
-		while((assoc = list_next(itr))) {
-			print_fields_str(SLURM_PRINT_VALUE, &name_field,
-					 assoc->user);
-			print_fields_str(SLURM_PRINT_VALUE, &acct_field,
-					 assoc->acct);
-			print_fields_uint(SLURM_PRINT_VALUE, &fs_field, 
-				   assoc->fairshare);
-			print_fields_uint(SLURM_PRINT_VALUE, &mc_field, 
-				   assoc->max_cpu_secs_per_job);
-			print_fields_uint(SLURM_PRINT_VALUE, &mj_field, 
-				   assoc->max_jobs);
-			print_fields_uint(SLURM_PRINT_VALUE, &mn_field, 
-				   assoc->max_nodes_per_job);
-			print_fields_uint(SLURM_PRINT_VALUE, &mw_field,
-				   assoc->max_wall_duration_per_job);
-			printf("\n");
-		}
-		list_iterator_destroy(itr);
-		list_destroy(print_fields_list);
-	
-		rc = acct_storage_g_add_associations(
-			db_conn, my_uid, user_assoc_list);
-		printf("---------------------------------------------------\n");
-		set = 1;
-	}
-	END_TIMER2("add cluster");
-		
-	info("Done adding cluster in %s", TIME_STR);
-		
-	if(rc == SLURM_SUCCESS) {
-		if(set) {
-			if(commit_check("Would you like to commit changes?")) {
-				acct_storage_g_commit(db_conn, 1);
-			} else {
-				printf(" Changes Discarded\n");
-				acct_storage_g_commit(db_conn, 0);
-			}
-		} else {
-			printf(" Nothing new added.\n");
-		}
-	} else {
-		printf(" error: Problem with requests.\n");
-	}
-
-	list_destroy(acct_list);
-	list_destroy(acct_assoc_list);
-	list_destroy(user_list);
-	list_destroy(user_assoc_list);
-	if(curr_acct_list)
-		list_destroy(curr_acct_list);
-	if(curr_assoc_list)
-		list_destroy(curr_assoc_list);
-	if(curr_cluster_list)
-		list_destroy(curr_cluster_list);
-	if(curr_user_list)
-		list_destroy(curr_user_list);
-}
-
 /* _usage - show the valid sacctmgr commands */
 void _usage () {
 	printf ("\
@@ -1406,7 +576,9 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
      -h or --help: equivalent to \"help\" command                          \n\
      --hide: equivalent to \"hide\" command                                \n\
      -i or --immediate: commit changes immediately                         \n\
+     -n or --no_header: no header will be added to the beginning of output \n\
      -o or --oneliner: equivalent to \"oneliner\" command                  \n\
+     -p or --parsable: output will be '|' delimited                        \n\
      -q or --quiet: equivalent to \"quiet\" command                        \n\
      -s or --associations: equivalent to \"associations\" command          \n\
      -v or --verbose: equivalent to \"verbose\" command                    \n\
@@ -1430,8 +602,6 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
      list <ENTITY> [<SPECS>]  display info of identified entity, default   \n\
                               is display all.                              \n\
      modify <ENTITY> <SPECS>  modify entity                                \n\
-     no_header                no header will be added to the beginning of  \n\
-                              output.                                      \n\
      oneliner                 report output one record per line.           \n\
      quiet                    print no messages other than error messages. \n\
      quit                     terminate this command.                      \n\
@@ -1441,7 +611,7 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
      version                  display tool version number.                 \n\
      !!                       Repeat the last command entered.             \n\
                                                                            \n\
-  <ENTITY> may be \"cluster\", \"account\", or \"user\".                   \n\
+  <ENTITY> may be \"cluster\", \"account\", \"user\", of \"coordinator\".  \n\
                                                                            \n\
   <SPECS> are different for each command entity pair.                      \n\
        list account       - Clusters=, Descriptions=, Format=, Names=,     \n\
@@ -1458,7 +628,7 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
                             Organizations=, and Parents=                   \n\
                                                                            \n\
        list associations  - Accounts=, Clusters=, Format=, ID=,            \n\
-                            Partitions=, Parent=, Users=                   \n\
+                            Partitions=, Parent=, Tree, Users=             \n\
                                                                            \n\
        list cluster       - Names= Format=                                 \n\
        add cluster        - Fairshare=, MaxCPUSecs=,                       \n\
@@ -1483,6 +653,9 @@ sacctmgr [<OPTION>] [<COMMAND>]                                            \n\
        delete user        - Accounts=, AdminLevel=, Clusters=,             \n\
                             DefaultAccounts=, and Names=                   \n\
                                                                            \n\
+       add coordinator    - Accounts=, and Names=                          \n\
+       delete coordinator - Accounts=, and Names=                          \n\
+                                                                           \n\
                                                                            \n\
   All commands entitys, and options are case-insensitive.               \n\n");
 	
diff --git a/src/sacctmgr/sacctmgr.h b/src/sacctmgr/sacctmgr.h
index df5f380b0de20975d75462ee3b74100a3e449e0c..5a23297855e9cf156c88d26a95bd9dcf38ffaa5e 100644
--- a/src/sacctmgr/sacctmgr.h
+++ b/src/sacctmgr/sacctmgr.h
@@ -86,6 +86,13 @@
 #define CKPT_WAIT	10
 #define	MAX_INPUT_FIELDS 128
 
+typedef struct {
+	acct_association_rec_t *assoc;
+	char *sort_name;
+	List childern;
+} sacctmgr_assoc_t;
+
+
 extern char *command_name;
 extern int exit_code;	/* sacctmgr's exit code, =1 on any error at any time */
 extern int exit_flag;	/* program to terminate if =1 */
@@ -119,15 +126,26 @@ extern int sacctmgr_delete_account(int argc, char *argv[]);
 extern int sacctmgr_delete_cluster(int argc, char *argv[]);
 extern int sacctmgr_delete_coord(int argc, char *argv[]);
 
+/* this has pointers to assoc_list so do not destroy assoc_list before
+ * using the list returned from this function.
+ */
+extern List sacctmgr_get_hierarchical_list(List assoc_list);
+
+extern int sacctmgr_dump_cluster(int argc, char *argv[]);
+
 /* common.c */
+extern void destroy_sacctmgr_assoc(void *object);
 extern int parse_option_end(char *option);
 extern char *strip_quotes(char *option, int *increased);
 extern void addto_char_list(List char_list, char *names);
-extern void destroy_sacctmgr_action(void *object);
 extern int notice_thread_init();
 extern int notice_thread_fini();
 extern int commit_check(char *warning);
 extern int get_uint(char *in_value, uint32_t *out_value, char *type);
+extern void sacctmgr_print_coord_list(type_t type, print_field_t *field,
+				      List value);
+extern int sort_coord_list(acct_coord_rec_t *coord_a,
+			   acct_coord_rec_t *coord_b);
 
 /* you need to free the objects returned from these functions */
 extern acct_association_rec_t *sacctmgr_find_association(char *user,
@@ -158,4 +176,12 @@ extern acct_cluster_rec_t *sacctmgr_find_cluster_from_list(
 	List cluster_list, char *name);
 
 
+/* file_functions.c */
+extern int print_file_sacctmgr_assoc_list(FILE *fd, 
+					  List sacctmgr_assoc_list,
+					  List user_list,
+					  List acct_list);
+
+extern void load_sacctmgr_cfg_file (int argc, char *argv[]);
+
 #endif
diff --git a/src/sacctmgr/user_functions.c b/src/sacctmgr/user_functions.c
index 1daa8de10fea64184b6e9e6df9853df26b7a675e..e30becaf55937e775f7965192b20cc2d4aa3d8d2 100644
--- a/src/sacctmgr/user_functions.c
+++ b/src/sacctmgr/user_functions.c
@@ -52,8 +52,10 @@ static int _set_cond(int *start, int argc, char *argv[],
 		if (strncasecmp (argv[i], "Set", 3) == 0) {
 			i--;
 			break;
-		} else if (strncasecmp (argv[i], "WithAssoc", 4) == 0) {
+		} else if (!end && strncasecmp (argv[i], "WithAssoc", 5) == 0) {
 			user_cond->with_assocs = 1;
+		} else if (strncasecmp (argv[i], "WithCoordinators", 5) == 0) {
+			user_cond->with_coords = 1;
 		} else if(!end && !strncasecmp(argv[i], "where", 5)) {
 			continue;
 		} else if(!end) {
@@ -192,64 +194,6 @@ static int _set_rec(int *start, int argc, char *argv[],
 	return 0;
 }
 
-/* static void _print_cond(acct_user_cond_t *user_cond) */
-/* { */
-/* 	ListIterator itr = NULL; */
-/* 	char *tmp_char = NULL; */
-
-/* 	if(!user_cond) { */
-/* 		error("no acct_user_cond_t * given"); */
-/* 		return; */
-/* 	} */
-
-/* 	if(user_cond->user_list && list_count(user_cond->user_list)) { */
-/* 		itr = list_iterator_create(user_cond->user_list); */
-/* 		printf("  Names           = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("                 or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(user_cond->def_acct_list */
-/* 	   && list_count(user_cond->def_acct_list)) { */
-/* 		itr = list_iterator_create(user_cond->def_acct_list); */
-/* 		printf("  Default Account = %s\n", (char *)list_next(itr)); */
-/* 		while((tmp_char = list_next(itr))) { */
-/* 			printf("                 or %s\n", tmp_char); */
-/* 		} */
-/* 	} */
-
-/* 	if(user_cond->qos != ACCT_QOS_NOTSET) */
-/* 		printf("  Qos        = %s\n",  */
-/* 		       acct_qos_str(user_cond->qos)); */
-
-/* 	if(user_cond->admin_level != ACCT_ADMIN_NOTSET) */
-/* 		printf("  Admin Level     = %s\n",  */
-/* 		       acct_admin_level_str(user_cond->admin_level)); */
-/* } */
-
-/* static void _print_rec(acct_user_rec_t *user) */
-/* { */
-/* 	if(!user) { */
-/* 		error("no acct_user_rec_t * given"); */
-/* 		return; */
-/* 	} */
-	
-/* 	if(user->name)  */
-/* 		printf("  Name            = %s\n", user->name);	 */
-		
-/* 	if(user->default_acct)  */
-/* 		printf("  Default Account = %s\n", user->default_acct); */
-		
-/* 	if(user->qos != ACCT_QOS_NOTSET) */
-/* 		printf("  Qos        = %s\n",  */
-/* 		       acct_qos_str(user->qos)); */
-
-/* 	if(user->admin_level != ACCT_ADMIN_NOTSET) */
-/* 		printf("  Admin Level     = %s\n",  */
-/* 		       acct_admin_level_str(user->admin_level)); */
-/* } */
-
 extern int sacctmgr_add_user(int argc, char *argv[])
 {
 	int rc = SLURM_SUCCESS;
@@ -789,6 +733,7 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 		PRINT_ACCOUNT,
 		PRINT_ADMIN,
 		PRINT_CLUSTER,
+		PRINT_COORDS,
 		PRINT_DACCT,
 		PRINT_FAIRSHARE,
 		PRINT_ID,
@@ -797,6 +742,8 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 		PRINT_MAXN,
 		PRINT_MAXW,
 		PRINT_QOS,
+		PRINT_QOS_GOLD,
+		PRINT_QOS_RAW,
 		PRINT_PID,
 		PRINT_PNAME,
 		PRINT_PART,
@@ -819,8 +766,9 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 		addto_char_list(format_list, "U,D,Q,Ad");
 		if(user_cond->with_assocs)
 			addto_char_list(format_list,
-					"C,Ac,Part,F,MaxC,MaxJ,MaxN,MaxW");
-			
+					"Cl,Ac,Part,F,MaxC,MaxJ,MaxN,MaxW");
+		if(user_cond->with_coords)
+			addto_char_list(format_list, "Coord");			
 	}
 
 	user_list = acct_storage_g_get_users(db_conn, user_cond);
@@ -847,11 +795,16 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 			field->name = xstrdup("Admin");
 			field->len = 9;
 			field->print_routine = print_fields_str;
-		} else if(!strncasecmp("Cluster", object, 1)) {
+		} else if(!strncasecmp("Cluster", object, 2)) {
 			field->type = PRINT_CLUSTER;
 			field->name = xstrdup("Cluster");
 			field->len = 10;
 			field->print_routine = print_fields_str;
+		} else if(!strncasecmp("Coordinators", object, 2)) {
+			field->type = PRINT_COORDS;
+			field->name = xstrdup("Coord Accounts");
+			field->len = 20;
+			field->print_routine = sacctmgr_print_coord_list;
 		} else if(!strncasecmp("Default", object, 1)) {
 			field->type = PRINT_DACCT;
 			field->name = xstrdup("Def Acct");
@@ -887,6 +840,16 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 			field->name = xstrdup("MaxWall");
 			field->len = 11;
 			field->print_routine = print_fields_time;
+		} else if(!strncasecmp("QOSGOLD", object, 4)) {
+			field->type = PRINT_QOS_GOLD;
+			field->name = xstrdup("QOS_GOLD");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
+		} else if(!strncasecmp("QOSRAW", object, 4)) {
+			field->type = PRINT_QOS_RAW;
+			field->name = xstrdup("QOS_RAW");
+			field->len = 7;
+			field->print_routine = print_fields_uint;
 		} else if(!strncasecmp("QOS", object, 1)) {
 			field->type = PRINT_QOS;
 			field->name = xstrdup("QOS");
@@ -915,6 +878,7 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 		list_append(print_fields_list, field);		
 	}
 	list_iterator_destroy(itr);
+	list_destroy(format_list);
 
 	itr = list_iterator_create(user_list);
 	itr2 = list_iterator_create(print_fields_list);
@@ -948,6 +912,12 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 							field,
 							assoc->cluster);
 						break;
+					case PRINT_COORDS:
+						field->print_routine(
+							SLURM_PRINT_VALUE,
+							field,
+							user->coord_accts);
+						break;
 					case PRINT_DACCT:
 						field->print_routine(
 							SLURM_PRINT_VALUE, 
@@ -1000,6 +970,18 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 							acct_qos_str(
 								user->qos));
 						break;
+					case PRINT_QOS_GOLD:
+						field->print_routine(
+							SLURM_PRINT_VALUE, 
+							field,
+							user->qos-1);
+						break;
+					case PRINT_QOS_RAW:
+						field->print_routine(
+							SLURM_PRINT_VALUE, 
+							field,
+							user->qos);
+						break;
 					case PRINT_PID:
 						field->print_routine(
 							SLURM_PRINT_VALUE, 
@@ -1051,6 +1033,12 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 						SLURM_PRINT_VALUE, field,
 						NULL);
 					break;
+				case PRINT_COORDS:
+					field->print_routine(
+						SLURM_PRINT_VALUE,
+						field,
+						user->coord_accts);
+					break;
 				case PRINT_DACCT:
 					field->print_routine(
 						SLURM_PRINT_VALUE, field,
@@ -1091,6 +1079,16 @@ extern int sacctmgr_list_user(int argc, char *argv[])
 						SLURM_PRINT_VALUE, field,
 						acct_qos_str(user->qos));
 					break;
+				case PRINT_QOS_GOLD:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						user->qos-1);
+					break;
+				case PRINT_QOS_RAW:
+					field->print_routine(
+						SLURM_PRINT_VALUE, field,
+						user->qos);
+					break;
 				case PRINT_PID:
 					field->print_routine(
 						SLURM_PRINT_VALUE, field,
@@ -1182,12 +1180,27 @@ extern int sacctmgr_modify_user(int argc, char *argv[])
 			return SLURM_SUCCESS;
 		}		
 	}
-
+	
 	notice_thread_init();
 	if(rec_set == 3 || rec_set == 1) { // process the account changes
 		if(cond_set == 2) {
 			rc = SLURM_ERROR;
-			goto assoc_start;
+			if(list_count(user_cond->assoc_cond->acct_list)) {
+				notice_thread_fini();
+				if(!commit_check(
+					   " You specified Accounts if your "
+					   "request.  Did you mean "
+					   "DefaultAccounts?\n")) {
+					goto assoc_start;
+				}
+				notice_thread_init();
+				list_transfer(user_cond->def_acct_list,
+					      user_cond->assoc_cond->acct_list);
+			} else {
+				printf(" There was a problem with your "
+				       "'where' options.\n");
+				goto assoc_start;
+			}
 		}
 		ret_list = acct_storage_g_modify_users(
 			db_conn, my_uid, user_cond, user);
diff --git a/src/salloc/opt.c b/src/salloc/opt.c
index 7e5992c186fd59c2364f8fa776a06d93d5908261..9e17c746bd650d9d4f610e30b5851f024561f2f5 100644
--- a/src/salloc/opt.c
+++ b/src/salloc/opt.c
@@ -118,6 +118,7 @@
 #define LONG_OPT_RAMDISK_IMAGE   0x123
 #define LONG_OPT_NOSHELL         0x124
 #define LONG_OPT_GET_USER_ENV    0x125
+#define LONG_OPT_NETWORK         0x126
 #define LONG_OPT_SOCKETSPERNODE  0x130
 #define LONG_OPT_CORESPERSOCKET  0x131
 #define LONG_OPT_THREADSPERCORE  0x132
@@ -326,6 +327,7 @@ env_vars_t env_vars[] = {
   {"SALLOC_EXCLUSIVE",     OPT_EXCLUSIVE,  NULL,               NULL           },
   {"SALLOC_OVERCOMMIT",    OPT_OVERCOMMIT, NULL,               NULL           },
   {"SALLOC_ACCTG_FREQ",    OPT_INT,        &opt.acctg_freq,    NULL           },
+  {"SALLOC_NETWORK",       OPT_STRING    , &opt.network,       NULL           },
   {NULL, 0, NULL, NULL}
 };
 
@@ -540,6 +542,7 @@ void set_options(const int argc, char **argv)
 		{"acctg-freq",    required_argument, 0, LONG_OPT_ACCTG_FREQ},
 		{"no-shell",      no_argument,       0, LONG_OPT_NOSHELL},
 		{"get-user-env",  optional_argument, 0, LONG_OPT_GET_USER_ENV},
+		{"network",       required_argument, 0, LONG_OPT_NETWORK},
 		{NULL,            0,                 0, 0}
 	};
 	char *opt_string = "+a:B:c:C:d:D:F:g:hHIJ:kK:L:m:n:N:Op:P:qR:st:uU:vVw:W:x:";
@@ -774,11 +777,15 @@ void set_options(const int argc, char **argv)
 			}
 			break;
 		case LONG_OPT_UID:
+			if (opt.euid != (uid_t) -1)
+				fatal ("duplicate --uid option");
 			opt.euid = uid_from_string (optarg);
 			if (opt.euid == (uid_t) -1)
 				fatal ("--uid=\"%s\" invalid", optarg);
 			break;
 		case LONG_OPT_GID:
+			if (opt.egid != (gid_t) -1)
+				fatal ("duplicate --gid option");
 			opt.egid = gid_from_string (optarg);
 			if (opt.egid == (gid_t) -1)
 				fatal ("--gid=\"%s\" invalid", optarg);
@@ -908,6 +915,10 @@ void set_options(const int argc, char **argv)
 			else
 				opt.get_user_env_time = 0;
 			break;
+		case LONG_OPT_NETWORK:
+			xfree(opt.network);
+			opt.network = xstrdup(optarg);
+			break;
 		default:
 			fatal("Unrecognized command line parameter %c",
 			      opt_char);
@@ -1121,9 +1132,6 @@ static bool _opt_verify(void)
 	if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid)) 
 		opt.gid = opt.egid;
 
-        if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid))
-	        opt.gid = opt.egid;
-
 	if (opt.immediate) {
 		char *sched_name = slurm_get_sched_type();
 		if (strcmp(sched_name, "sched/wiki") == 0) {
@@ -1134,6 +1142,11 @@ static bool _opt_verify(void)
 		xfree(sched_name);
 	}
 
+#ifdef HAVE_AIX
+	if (opt.network == NULL)
+		opt.network = "us,sn_all,bulk_xfer";
+#endif
+
 	return verified;
 }
 
@@ -1279,6 +1292,7 @@ static void _opt_list()
 	info("account        : %s", opt.account);
 	info("comment        : %s", opt.comment);
 	info("dependency     : %s", opt.dependency);
+	info("network        : %s", opt.network);
 	str = print_constraints();
 	info("constraints    : %s", str);
 	xfree(str);
@@ -1339,6 +1353,7 @@ static void _usage(void)
 "              [--mail-type=type] [--mail-user=user][--nice[=value]]\n"
 "              [--bell] [--no-bell] [--kill-command[=signal]]\n"
 "              [--nodefile=file] [--nodelist=hosts] [--exclude=hosts]\n"
+"              [--network=type]\n"
 "              executable [args...]\n");
 }
 
@@ -1425,6 +1440,11 @@ static void _help(void)
 	slurm_conf_unlock();
 
         printf("\n"
+#ifdef HAVE_AIX				/* AIX/Federation specific options */
+  "AIX related options:\n"
+  "  --network=type              communication protocol to be used\n"
+  "\n"
+#endif
 #ifdef HAVE_BG				/* Blue gene specific options */
 "\n"
   "Blue Gene related options:\n"
diff --git a/src/salloc/opt.h b/src/salloc/opt.h
index 46138a9ece48778697c2f0fe060a1dde21a6cc8a..972444517d95c9382d75ee8cdd176ef8cfb6a8fb 100644
--- a/src/salloc/opt.h
+++ b/src/salloc/opt.h
@@ -114,6 +114,7 @@ typedef struct salloc_options {
 	bool contiguous;	/* --contiguous			*/
 	char *nodelist;		/* --nodelist=node1,node2,...	*/
 	char *exc_nodes;	/* --exclude=node1,node2,... -x	*/
+	char *network;		/* --network=			*/
 
 	/* BLUEGENE SPECIFIC */
 	uint16_t geometry[SYSTEM_DIMENSIONS]; /* --geometry, -g	*/
diff --git a/src/salloc/salloc.c b/src/salloc/salloc.c
index be782a7f31e8eb5f196b0f3bcc81159b1962f383..edb65cb94d70fce8145eaffe3367791a47129b67 100644
--- a/src/salloc/salloc.c
+++ b/src/salloc/salloc.c
@@ -221,6 +221,8 @@ int main(int argc, char *argv[])
 		env_array_append_fmt(&env, "SLURM_TASK_MEM", "%d",
 			opt.task_mem);
 	}
+	if (opt.network)
+		env_array_append_fmt(&env, "SLURM_NETWORK", "%s", opt.network);
 	env_array_set_environment(env);
 	env_array_free(env);
 	pthread_mutex_lock(&allocation_state_lock);
@@ -310,6 +312,7 @@ static int fill_job_desc_from_opts(job_desc_msg_t *desc)
 		desc->plane_size = opt.plane_size;
 	if (opt.licenses)
 		desc->licenses = xstrdup(opt.licenses);
+	desc->network = opt.network;
 	if (opt.nice)
 		desc->nice = NICE_OFFSET + opt.nice;
 	desc->mail_type = opt.mail_type;
diff --git a/src/sbatch/opt.c b/src/sbatch/opt.c
index 5c3daa39e9ec61d9369e6b2e0a5b0491a5973e4c..365782b68d917a3c395e87e1549c1ee79d4d9a49 100644
--- a/src/sbatch/opt.c
+++ b/src/sbatch/opt.c
@@ -81,6 +81,7 @@
 #define OPT_BOOL        0x06
 #define OPT_CORE        0x07
 #define OPT_CONN_TYPE	0x08
+#define OPT_DISTRIB	0x09
 #define OPT_NO_ROTATE	0x0a
 #define OPT_GEOMETRY	0x0b
 #define OPT_MULTI	0x0f
@@ -114,6 +115,7 @@
 #define LONG_OPT_COMMENT     0x117
 #define LONG_OPT_WRAP        0x118
 #define LONG_OPT_REQUEUE     0x119
+#define LONG_OPT_NETWORK     0x120
 #define LONG_OPT_SOCKETSPERNODE  0x130
 #define LONG_OPT_CORESPERSOCKET  0x131
 #define LONG_OPT_THREADSPERCORE  0x132
@@ -321,6 +323,7 @@ env_vars_t env_vars[] = {
   {"SBATCH_BLRTS_IMAGE",   OPT_STRING,     &opt.blrtsimage,    NULL           },
   {"SBATCH_CONN_TYPE",     OPT_CONN_TYPE,  NULL,               NULL           },
   {"SBATCH_DEBUG",         OPT_DEBUG,      NULL,               NULL           },
+  {"SBATCH_DISTRIBUTION",  OPT_DISTRIB ,   NULL,               NULL           },
   {"SBATCH_GEOMETRY",      OPT_GEOMETRY,   NULL,               NULL           },
   {"SBATCH_IMMEDIATE",     OPT_BOOL,       &opt.immediate,     NULL           },
   {"SBATCH_JOBID",         OPT_INT,        &opt.jobid,         NULL           },
@@ -337,6 +340,7 @@ env_vars_t env_vars[] = {
   {"SBATCH_EXCLUSIVE",     OPT_EXCLUSIVE,  NULL,               NULL           },
   {"SBATCH_OPEN_MODE",     OPT_OPEN_MODE,  NULL,               NULL           },
   {"SBATCH_ACCTG_FREQ",    OPT_INT,        &opt.acctg_freq,    NULL           },
+  {"SBATCH_NETWORK",       OPT_STRING,     &opt.network,       NULL           },
   {NULL, 0, NULL, NULL}
 };
 
@@ -407,6 +411,15 @@ _process_env_var(env_vars_t *e, const char *val)
 		}
 		break;
 
+	case OPT_DISTRIB:
+		opt.distribution = verify_dist_type(optarg, 
+						    &opt.plane_size);
+		if (opt.distribution == SLURM_DIST_UNKNOWN)
+			error("distribution type `%s' is invalid", optarg);
+		else
+			setenv("SLURM_DISTRIBUTION", optarg, 1);
+		break;
+
 	case OPT_NODES:
 		opt.nodes_set = verify_node_count( val, 
 						   &opt.min_nodes, 
@@ -542,6 +555,7 @@ static struct option long_options[] = {
 	{"open-mode",     required_argument, 0, LONG_OPT_OPEN_MODE},
 	{"acctg-freq",    required_argument, 0, LONG_OPT_ACCTG_FREQ},
 	{"propagate",     optional_argument, 0, LONG_OPT_PROPAGATE},
+	{"network",       required_argument, 0, LONG_OPT_NETWORK},
 	{NULL,            0,                 0, 0}
 };
 
@@ -1007,7 +1021,8 @@ static void _set_options(int argc, char **argv)
 				error("distribution type `%s' " 
 				      "is not recognized", optarg);
 				exit(1);
-			}
+			} 
+			setenv("SLURM_DISTRIBUTION", optarg, 1);
 			break;
 		case 'n':
 			opt.nprocs_set = true;
@@ -1156,11 +1171,15 @@ static void _set_options(int argc, char **argv)
 			opt.jobid_set = true;
 			break;
 		case LONG_OPT_UID:
+			if (opt.euid != (uid_t) -1)
+				fatal ("duplicate --uid option");
 			opt.euid = uid_from_string (optarg);
 			if (opt.euid == (uid_t) -1)
 				fatal ("--uid=\"%s\" invalid", optarg);
 			break;
 		case LONG_OPT_GID:
+			if (opt.egid != (gid_t) -1)
+				fatal ("duplicate --gid option");
 			opt.egid = gid_from_string (optarg);
 			if (opt.egid == (gid_t) -1)
 				fatal ("--gid=\"%s\" invalid", optarg);
@@ -1310,6 +1329,11 @@ static void _set_options(int argc, char **argv)
 			else
 				opt.propagate = xstrdup("ALL");
 			break;
+		case LONG_OPT_NETWORK:
+			xfree(opt.network);
+			opt.network = xstrdup(optarg);
+			setenv("SLURM_NETWORK", opt.network, 1);
+			break;
 		default:
 			if (spank_process_option (opt_char, optarg) < 0)
 				 exit (1);
@@ -1867,9 +1891,6 @@ static bool _opt_verify(void)
 	if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid)) 
 		opt.gid = opt.egid;
 
-        if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid))
-	        opt.gid = opt.egid;
-
 	if (opt.immediate) {
 		char *sched_name = slurm_get_sched_type();
 		if (strcmp(sched_name, "sched/wiki") == 0) {
@@ -1895,6 +1916,13 @@ static bool _opt_verify(void)
 	if (opt.acctg_freq >= 0)
 		setenvf(NULL, "SLURM_ACCTG_FREQ", "%d", opt.acctg_freq); 
 
+#ifdef HAVE_AIX
+	if (opt.network == NULL) {
+		opt.network = "us,sn_all,bulk_xfer";
+		setenv("SLURM_NETWORK", opt.network, 1);
+	}
+#endif
+
 	return verified;
 }
 
@@ -2070,6 +2098,7 @@ static void _opt_list()
 	xfree(str);
 	info("reboot         : %s", opt.reboot ? "no" : "yes");
 	info("rotate         : %s", opt.no_rotate ? "yes" : "no");
+	info("network        : %s", opt.network);
 
 	if (opt.blrtsimage)
 		info("BlrtsImage     : %s", opt.blrtsimage);
@@ -2125,6 +2154,7 @@ static void _usage(void)
 "              [--mail-type=type] [--mail-user=user][--nice[=value]]\n"
 "              [--requeue] [--no-requeue] [--ntasks-per-node=n] [--propagate]\n"
 "              [--nodefile=file] [--nodelist=hosts] [--exclude=hosts]\n"
+"              [--network=type]\n"
 "              executable [args...]\n");
 }
 
@@ -2151,6 +2181,8 @@ static void _help(void)
 "  -k, --no-kill               do not kill job on node failure\n"
 "  -s, --share                 share nodes with other jobs\n"
 "  -J, --job-name=jobname      name of job\n"
+"  -m, --distribution=type     distribution method for processes to nodes\n"
+"                              (type = block|cyclic|arbitrary)\n"
 "      --jobid=id              run under already allocated job\n"
 "  -v, --verbose               verbose mode (multiple -v's increase verbosity)\n"
 "  -q, --quiet                 quiet mode (suppress informational messages)\n"
@@ -2214,6 +2246,11 @@ static void _help(void)
 	spank_print_options (stdout, 6, 30);
 
         printf("\n"
+#ifdef HAVE_AIX				/* AIX/Federation specific options */
+"AIX related options:\n"
+"      --network=type          communication protocol to be used\n"
+"\n"
+#endif
 #ifdef HAVE_BG				/* Blue gene specific options */
 "Blue Gene related options:\n"
 "  -g, --geometry=XxYxZ        geometry constraints of the job\n"
diff --git a/src/sbatch/opt.h b/src/sbatch/opt.h
index 92565efb5c2dc71e6308f7b6ea49b0c363d3b5d0..b746cedf2385a2bf88724ff829572ded9c1c7175 100644
--- a/src/sbatch/opt.h
+++ b/src/sbatch/opt.h
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  *  opt.h - definitions for srun option processing
- *  $Id: opt.h 13771 2008-04-02 20:03:47Z jette $
+ *  $Id: opt.h 14338 2008-06-24 23:10:32Z jette $
  *****************************************************************************
  *  Copyright (C) 2002-2006 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -103,6 +103,7 @@ typedef struct sbatch_options {
 	bool overcommit;	/* --overcommit -O		*/
 	uint16_t shared;	/* --share,   -s		*/
 	char *licenses;		/* --licenses, -L		*/
+	char *network;		/* --network=			*/
 	int  quiet;
 	int  verbose;
 	char *wrap;
diff --git a/src/sbatch/sbatch.c b/src/sbatch/sbatch.c
index b0da0b4dc6e362525e941060fb164bef2deee6ef..b94dc55428e3f943d2f18eaa3deb80177e2fc870 100644
--- a/src/sbatch/sbatch.c
+++ b/src/sbatch/sbatch.c
@@ -1,7 +1,7 @@
 /*****************************************************************************\
  *  sbatch.c - Submit a SLURM batch script.
  *
- *  $Id: sbatch.c 14226 2008-06-10 21:12:53Z jette $
+ *  $Id: sbatch.c 14420 2008-07-02 19:52:49Z jette $
  *****************************************************************************
  *  Copyright (C) 2006-2007 The Regents of the University of California.
  *  Copyright (C) 2008 Lawrence Livermore National Security.
@@ -179,6 +179,7 @@ static int fill_job_desc_from_opts(job_desc_msg_t *desc)
 	desc->task_dist  = opt.distribution;
 	if (opt.plane_size != NO_VAL)
 		desc->plane_size = opt.plane_size;
+	desc->network = opt.network;
 	if (opt.nice)
 		desc->nice = NICE_OFFSET + opt.nice;
 	desc->mail_type = opt.mail_type;
diff --git a/src/slurmctld/acct_policy.c b/src/slurmctld/acct_policy.c
index 10daf04456c824dafad48b0aca730f69b3dffad9..75361fbc17befe47df53122bac3dd56df38c2336 100644
--- a/src/slurmctld/acct_policy.c
+++ b/src/slurmctld/acct_policy.c
@@ -48,6 +48,20 @@
 
 #define _DEBUG 0
 
+
+static void _cancel_job(struct job_record *job_ptr)
+{
+	time_t now = time(NULL);
+
+	last_job_update = now;
+	job_ptr->job_state = JOB_FAILED;
+	job_ptr->exit_code = 1;
+	job_ptr->state_reason = FAIL_BANK_ACCOUNT;
+	job_ptr->start_time = job_ptr->end_time = now;
+	job_completion_logger(job_ptr);
+	delete_job_details(job_ptr);
+}
+
 static bool _valid_job_assoc(struct job_record *job_ptr)
 {
 	acct_association_rec_t assoc_rec, *assoc_ptr;
@@ -108,18 +122,24 @@ extern void acct_policy_job_fini(struct job_record *job_ptr)
 }
 
 /*
- * acct_policy_job_runnable - Determine of the specified job
- *	can execute right now or not depending upon accounting
- *	policy (e.g. running job limit for this association).
+ * acct_policy_job_runnable - Determine of the specified job can execute
+ *	right now or not depending upon accounting policy (e.g. running
+ *	job limit for this association). If the association limits prevent
+ *	the job from ever running (lowered limits since job submissin), 
+ *	then cancel the job.
  */
 extern bool acct_policy_job_runnable(struct job_record *job_ptr)
 {
 	acct_association_rec_t *assoc_ptr;
+	uint32_t time_limit;
 
 	if (!accounting_enforce)
 		return true;
-	if (!_valid_job_assoc(job_ptr))
+
+	if (!_valid_job_assoc(job_ptr)) {
+		_cancel_job(job_ptr);
 		return false;
+	}
 
 	assoc_ptr = job_ptr->assoc_ptr;
 #if _DEBUG
@@ -129,7 +149,42 @@ extern bool acct_policy_job_runnable(struct job_record *job_ptr)
 
 	if ((assoc_ptr->max_jobs != NO_VAL) &&
 	    (assoc_ptr->max_jobs != INFINITE) &&
-	    (assoc_ptr->used_jobs >= assoc_ptr->max_jobs))
+	    (assoc_ptr->used_jobs >= assoc_ptr->max_jobs)) {
+		job_ptr->state_reason = WAIT_ASSOC_LIMIT;
 		return false;
+	}
+
+	/* if the association limits have changed since job
+	 * submission and job can not run, then kill it */
+	if ((assoc_ptr->max_wall_duration_per_job != NO_VAL) &&
+	    (assoc_ptr->max_wall_duration_per_job != INFINITE)) {
+		time_limit = assoc_ptr->max_wall_duration_per_job;
+		if ((job_ptr->time_limit != NO_VAL) &&
+		    (job_ptr->time_limit > time_limit)) {
+			info("job %u being cancelled, time limit exceeds "
+			     "account max (%u > %u)",
+			     job_ptr->job_id, job_ptr->time_limit, time_limit);
+			_cancel_job(job_ptr);
+			return false;
+		}
+	}
+
+	if ((assoc_ptr->max_nodes_per_job != NO_VAL) &&
+	    (assoc_ptr->max_nodes_per_job != INFINITE)) {
+		if (job_ptr->details->min_nodes > 
+		    assoc_ptr->max_nodes_per_job) {
+			info("job %u being cancelled,  min node limit exceeds "
+			     "account max (%u > %u)",
+			     job_ptr->job_id, job_ptr->details->min_nodes, 
+			     assoc_ptr->max_nodes_per_job);
+			_cancel_job(job_ptr);
+			return false;
+		}
+	}
+
+	/* NOTE: We can't enforce assoc_ptr->max_cpu_secs_per_job at this
+	 * time because we don't have access to a CPU count for the job
+	 * due to how all of the job's specifications interact */
+
 	return true;
 }
diff --git a/src/slurmctld/acct_policy.h b/src/slurmctld/acct_policy.h
index 6bed6308c816f4403e41e2a8711b77d17ba7f8a1..cc9c16a62e9a3c79ce2ecd84b26a41cb47737bdf 100644
--- a/src/slurmctld/acct_policy.h
+++ b/src/slurmctld/acct_policy.h
@@ -51,9 +51,11 @@ extern void acct_policy_job_begin(struct job_record *job_ptr);
 extern void acct_policy_job_fini(struct job_record *job_ptr);
 
 /*
- * acct_policy_job_runnable - Determine of the specified job
- *	can execute right now or not depending upon accounting
- *	policy (e.g. running job limit for this association).
+ * acct_policy_job_runnable - Determine of the specified job can execute
+ *	right now or not depending upon accounting policy (e.g. running
+ *	job limit for this association). If the association limits prevent
+ *	the job from ever running (lowered limits since job submissin), 
+ *	then cancel the job.
  */
 extern bool acct_policy_job_runnable(struct job_record *job_ptr);
 
diff --git a/src/slurmctld/job_scheduler.c b/src/slurmctld/job_scheduler.c
index 3274da8fb252472139f93ed5614290efe681b8aa..457827d24aa0f7826546097f1d417ae0f109c304 100644
--- a/src/slurmctld/job_scheduler.c
+++ b/src/slurmctld/job_scheduler.c
@@ -284,10 +284,8 @@ extern int schedule(void)
 		job_ptr = job_queue[i].job_ptr;
 		if (job_ptr->priority == 0)	/* held */
 			continue;
-		if (!acct_policy_job_runnable(job_ptr)) {
-			job_ptr->state_reason = WAIT_ASSOC_LIMIT;
+		if (!acct_policy_job_runnable(job_ptr))
 			continue;
-		}
 		if (_failed_partition(job_ptr->part_ptr, failed_parts, 
 				      failed_part_cnt)) {
 			job_ptr->state_reason = WAIT_PRIORITY;
diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c
index 1c63015a297b3c4ba625e1d8568c84aa7198faee..0bc50f8e961967d620ce6f64b5b0ca3acd23f8bc 100644
--- a/src/slurmctld/node_scheduler.c
+++ b/src/slurmctld/node_scheduler.c
@@ -834,11 +834,8 @@ extern int select_nodes(struct job_record *job_ptr, bool test_only,
 	xassert(job_ptr);
 	xassert(job_ptr->magic == JOB_MAGIC);
 
-	if (!acct_policy_job_runnable(job_ptr)) {
-		job_ptr->state_reason = WAIT_ASSOC_LIMIT;
-		last_job_update = now;
+	if (!acct_policy_job_runnable(job_ptr))
 		return ESLURM_ACCOUNTING_POLICY;
-	}
 
 	/* identify partition */
 	if (part_ptr == NULL) {
diff --git a/src/slurmctld/read_config.c b/src/slurmctld/read_config.c
index b219cda17abaa16ebc9ba236f1e8a2d260ec6ea5..cb1910654ca97a95ca9092737528937afaf69010 100644
--- a/src/slurmctld/read_config.c
+++ b/src/slurmctld/read_config.c
@@ -374,19 +374,19 @@ static int _build_single_nodeline_info(slurm_conf_node_t *node_ptr,
 	}
 
 	if ((alias_list = hostlist_create(node_ptr->nodenames)) == NULL) {
-		error("Unable to create NodeName list from %s",
+		fatal("Unable to create NodeName list from %s",
 		      node_ptr->nodenames);
 		error_code = errno;
 		goto cleanup;
 	}
 	if ((hostname_list = hostlist_create(node_ptr->hostnames)) == NULL) {
-		error("Unable to create NodeHostname list from %s",
+		fatal("Unable to create NodeHostname list from %s",
 		      node_ptr->hostnames);
 		error_code = errno;
 		goto cleanup;
 	}
 	if ((address_list = hostlist_create(node_ptr->addresses)) == NULL) {
-		error("Unable to create NodeAddr list from %s",
+		fatal("Unable to create NodeAddr list from %s",
 		      node_ptr->addresses);
 		error_code = errno;
 		goto cleanup;
diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h
index cd16cf877239fa8367fbf38d80563bc00d31e20a..3bfa240f37e410e4c198e6b2f35f80a8564a4b93 100644
--- a/src/slurmctld/slurmctld.h
+++ b/src/slurmctld/slurmctld.h
@@ -54,6 +54,7 @@
 #include <pthread.h>
 /* #include <stdlib.h> */
 #include <time.h>
+#include <strings.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/src/slurmd/slurmd/req.c b/src/slurmd/slurmd/req.c
index 86e2523843b183b7af5555291f9fd6c5657ee8ed..dab7c08eebe584255b48a26ca40771625c0fc7a6 100644
--- a/src/slurmd/slurmd/req.c
+++ b/src/slurmd/slurmd/req.c
@@ -1702,11 +1702,11 @@ _rpc_timelimit(slurm_msg_t *msg)
 	slurm_close_accepted_conn(msg->conn_fd);
 	msg->conn_fd = -1;
 
+	_kill_all_active_steps(req->job_id, SIGXCPU, true);
 	nsteps = xcpu_signal(SIGTERM, req->nodes) +
 		_kill_all_active_steps(req->job_id, SIGTERM, false);
 	verbose( "Job %u: timeout: sent SIGTERM to %d active steps", 
 	         req->job_id, nsteps );
-	_kill_all_active_steps(req->job_id, SIGXCPU, true);
 
 	/* Revoke credential, send SIGKILL, run epilog, etc. */
 	_rpc_terminate_job(msg); 
diff --git a/src/slurmd/slurmstepd/req.c b/src/slurmd/slurmstepd/req.c
index 110083f7ea3e5712bc43e2c7cbcc832998ee2acb..3d85eb0bad0cd36a2b95f76118ee0e1f56620cc2 100644
--- a/src/slurmd/slurmstepd/req.c
+++ b/src/slurmd/slurmstepd/req.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  *  src/slurmd/slurmstepd/req.c - slurmstepd domain socket request handling
- *  $Id: req.c 13959 2008-04-30 21:00:47Z jette $
+ *  $Id: req.c 14422 2008-07-02 21:48:19Z jette $
  *****************************************************************************
  *  Copyright (C) 2005 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -717,26 +717,29 @@ _handle_signal_container(int fd, slurmd_job_t *job, uid_t uid)
 		goto done;
 	}
 
-	/*
-	 * Signal the container
-	 */
 	if (job->nodeid == 0) {
 		static int msg_sent = 0;
+		char *entity;
+		if (job->stepid == SLURM_BATCH_SCRIPT)
+			entity = "JOB";
+		else
+			entity = "STEP";
 		/* Not really errors, 
 		 * but we want messages displayed by default */
 		if (msg_sent)
 			;
 		else if (sig == SIGXCPU) {
-			error("*** JOB CANCELLED DUE TO TIME LIMIT ***");
+			error("*** %s CANCELLED DUE TO TIME LIMIT ***", entity);
 			msg_sent = 1;
 		} else if (sig == SIG_NODE_FAIL) {
-			error("*** JOB CANCELLED DUE TO NODE FAILURE ***");
+			error("*** %s CANCELLED DUE TO NODE FAILURE ***", entity);
 			msg_sent = 1;
 		} else if (sig == SIG_FAILURE) {
-			error("*** JOB CANCELLED DUE TO SYSTEM FAILURE ***");
+			error("*** %s FAILED (non-zero exit code or other "
+			      "failure mode) ***", entity);
 			msg_sent = 1;
 		} else if ((sig == SIGTERM) || (sig == SIGKILL)) {
-			error("*** JOB CANCELLED ***");
+			error("*** %s CANCELLED ***", entity);
 			msg_sent = 1;
 		}
 	}
@@ -744,13 +747,16 @@ _handle_signal_container(int fd, slurmd_job_t *job, uid_t uid)
 		goto done;
 
 	pthread_mutex_lock(&suspend_mutex);
-	if (suspended) {
+	if (suspended && (sig != SIGKILL)) {
 		rc = -1;
 		errnum = ESLURMD_STEP_SUSPENDED;
 		pthread_mutex_unlock(&suspend_mutex);
 		goto done;
 	}
 
+	/*
+	 * Signal the container
+	 */
 	if (slurm_container_signal(job->cont_id, sig) < 0) {
 		rc = -1;
 		errnum = errno;
diff --git a/src/slurmdbd/proc_req.c b/src/slurmdbd/proc_req.c
index 6f63b1ece476b1f39659eb251dc80dd99efe3cf1..21952ea416774ec3423a65223beeffa18a04f764 100644
--- a/src/slurmdbd/proc_req.c
+++ b/src/slurmdbd/proc_req.c
@@ -380,7 +380,7 @@ static int _add_account_coords(void *db_conn,
 		itr2 = list_iterator_create(user.coord_accts);
 		while((acct = list_next(itr))) {
 			while((coord = list_next(itr2))) {
-				if(!strcasecmp(coord->acct_name, acct))
+				if(!strcasecmp(coord->name, acct))
 					break;
 			}
 			if(!coord)  {
@@ -457,7 +457,7 @@ static int _add_assocs(void *db_conn,
 				account = object->parent_acct;
 			list_iterator_reset(itr2);
 			while((coord = list_next(itr2))) {
-				if(!strcasecmp(coord->acct_name, account))
+				if(!strcasecmp(coord->name, account))
 					break;
 			}
 			if(!coord) 
@@ -1140,7 +1140,7 @@ static int   _modify_accounts(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1155,7 +1155,6 @@ static int   _modify_accounts(void *db_conn,
 	slurmdbd_pack_list_msg(DBD_GOT_LIST, &list_msg, *out_buffer);
 	if(list_msg.my_list)
 		list_destroy(list_msg.my_list);
-	*out_buffer = make_dbd_rc_msg(rc, comment, DBD_MODIFY_ACCOUNTS);
 	return rc;
 }
 
@@ -1196,7 +1195,7 @@ static int   _modify_assocs(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1257,7 +1256,7 @@ static int   _modify_clusters(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1326,7 +1325,7 @@ static int   _modify_users(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1534,7 +1533,7 @@ static int   _remove_accounts(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1568,8 +1567,9 @@ static int   _remove_account_coords(void *db_conn,
 	    SLURM_SUCCESS) {
 		comment = "Failed to unpack DBD_REMOVE_ACCOUNT_COORDS message";
 		error("%s", comment);
-		rc = SLURM_ERROR;
-		goto end_it;
+		*out_buffer = make_dbd_rc_msg(SLURM_ERROR, comment,
+					      DBD_ADD_ACCOUNT_COORDS);
+		return SLURM_ERROR;
 	}
 	
 	/* All authentication needs to be done inside the plugin since we are
@@ -1589,7 +1589,7 @@ static int   _remove_account_coords(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1607,11 +1607,6 @@ static int   _remove_account_coords(void *db_conn,
 		list_destroy(list_msg.my_list);
 
 	return rc;
-end_it:
-	slurmdbd_free_acct_coord_msg(get_msg);
-	*out_buffer = make_dbd_rc_msg(rc, comment, DBD_ADD_ACCOUNT_COORDS);
-	return rc;
-
 }
 
 static int   _remove_assocs(void *db_conn,
@@ -1649,7 +1644,7 @@ static int   _remove_assocs(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1711,7 +1706,7 @@ static int   _remove_clusters(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
@@ -1771,7 +1766,7 @@ static int   _remove_users(void *db_conn,
 			comment = "Request didn't affect anything";
 			rc = SLURM_SUCCESS;
 		} else {
-			comment = "Unkown issue";
+			comment = "Unknown issue";
 			rc = SLURM_ERROR;
 		}
 		error("%s", comment);
diff --git a/src/sreport/sreport.c b/src/sreport/sreport.c
index a348dbb59fa4a01034ed461e69b4a11d8a6aef4f..08715ad0e8ea6ab9d5504a57a8cb17d264608c00 100644
--- a/src/sreport/sreport.c
+++ b/src/sreport/sreport.c
@@ -490,10 +490,11 @@ void _usage () {
 	printf ("\
 sreport [<OPTION>] [<COMMAND>]                                             \n\
     Valid <OPTION> values are:                                             \n\
+     -a or --all_clusters: Use all clusters instead of current             \n\
      -h or --help: equivalent to \"help\" command                          \n\
-     -o or --oneliner: equivalent to \"oneliner\" command                  \n\
+     -n or --no_header: equivalent to \"no_header\" command                \n\
      -q or --quiet: equivalent to \"quiet\" command                        \n\
-     -s or --associations: equivalent to \"associations\" command          \n\
+     -p or --parsable: equivalent to \"parsable\" command                  \n\
      -v or --verbose: equivalent to \"verbose\" command                    \n\
      -V or --version: equivalent to \"version\" command                    \n\
                                                                            \n\
@@ -504,18 +505,63 @@ sreport [<OPTION>] [<COMMAND>]                                             \n\
     Valid <COMMAND> values are:                                            \n\
      exit                     terminate sreport                            \n\
      help                     print this description of use.               \n\
-     no_header                no header will be added to the beginning of  \n\
-                              output.                                      \n\
-     oneliner                 report output one record per line.           \n\
      quiet                    print no messages other than error messages. \n\
      quit                     terminate this command.                      \n\
-     parsable                 output will be | delimited                   \n\
      verbose                  enable detailed logging.                     \n\
      version                  display tool version number.                 \n\
      !!                       Repeat the last command entered.             \n\
                                                                            \n\
+    Valid report types are:                                                \n\
+     cluster <REPORT> <OPTIONS>                                            \n\
+     job <REPORT> <OPTIONS>                                                \n\
+     user <REPORT> <OPTIONS>                                               \n\
                                                                            \n\
-  All commands, entities, and options are case-insensitive.              \n\n");
+  <REPORT> is different for each report type.                              \n\
+     cluster - Utilization                                                 \n\
+     job     - Sizes                                                       \n\
+     user    - TopUsage                                                    \n\
+                                                                           \n\
+  <OPTIONS> are different for each report type.                            \n\
+                                                                           \n\
+     COMMON FOR ALL TYPES                                                  \n\
+             - All_Clusters     - Use all monitored clusters default is    \n\
+                                  local cluster.                           \n\
+             - End=<OPT>        - Period ending for report.                \n\
+                                  Default is 23:59:59 of previous day.     \n\
+             - Format=<OPT>     - Comma separated list of fields to display\n\
+                                  in report.                               \n\
+             - Start=<OPT>      - Period start for report.                 \n\
+                                  Default is 00:00:00 of previous day.     \n\
+                                                                           \n\
+     cluster - Names=<OPT>      - List of clusters to include in report    \n\
+                                  Default is local cluster.                \n\
+                                                                           \n\
+     job     - Accounts=<OPT>   - List of accounts to use for the report   \n\
+                                  Default is all.                          \n\
+             - Clusters=<OPT>   - List of clusters to include in report.   \n\
+                                  Default is local cluster.                \n\
+             - GID=<OPT>        - List of group ids to include in report   \n\
+                                  Default is all.                          \n\
+             - Grouping=<OPT>   - Comma separated list of size groupings.  \n\
+                                  (i.e. 50,100,150 would group job cpu count\n\
+                                   1-49, 50-99, 100-149, > 150).           \n\
+             - Jobs=<OPT>       - List of jobs/steps to include in report. \n\
+                                  Default is all.                          \n\
+             - Partitions=<OPT> - List of partitions jobs ran on to include\n\
+                                  in report.  Default is all.              \n\
+             - Users=<OPT>      - List of users jobs to include in report. \n\
+                                  Default is all.                          \n\
+                                                                           \n\
+     user    - Clusters=<OPT>   - List of clusters to include in report.   \n\
+                                  Default is local cluster.                \n\
+             - Group            - Group all accounts together for each user.\n\
+                                  Default is a separate entry for each user\n\
+                                  and account reference.                   \n\
+             - Users=<OPT>      - List of users jobs to include in report. \n\
+                                  Default is all.                          \n\
+                                                                           \n\
+                                                                           \n\
+  All commands and options are case-insensitive.                         \n\n");
 	
 }
 
diff --git a/src/sreport/user_reports.c b/src/sreport/user_reports.c
index d83b9d886500cfa76923b256f0396e1fc8a42fac..fa1ff534029e22398f1e74f0b342d5dbe78ea726 100644
--- a/src/sreport/user_reports.c
+++ b/src/sreport/user_reports.c
@@ -52,6 +52,7 @@ typedef struct {
 	List acct_list; /* list of char *'s */
 	uint64_t cpu_secs;
 	char *name;
+	uid_t uid;
 } local_user_rec_t;
 
 typedef struct {
@@ -154,6 +155,8 @@ static int _set_cond(int *start, int argc, char *argv[],
 		} else if(!end && !strncasecmp(argv[i], "all_clusters", 1)) {
 			local_cluster_flag = 1;
 			continue;
+		} else if (!end && !strncasecmp(argv[i], "group", 1)) {
+			group_accts = 1;
 		} else if(!end) {
 			addto_char_list(user_cond->user_list, argv[i]);
 			set = 1;
@@ -171,8 +174,6 @@ static int _set_cond(int *start, int argc, char *argv[],
 		} else if (strncasecmp (argv[i], "Format", 1) == 0) {
 			if(format_list)
 				addto_char_list(format_list, argv[i]+end);
-		} else if (strncasecmp (argv[i], "group", 1) == 0) {
-			group_accts = 1;
 		} else if (strncasecmp (argv[i], "Start", 1) == 0) {
 			assoc_cond->usage_start = parse_time(argv[i]+end);
 			set = 1;
@@ -318,52 +319,61 @@ extern int user_top(int argc, char *argv[])
 
 	itr = list_iterator_create(user_list);
 	cluster_itr = list_iterator_create(cluster_list);
-
 	while((user = list_next(itr))) {
+		struct passwd *passwd_ptr = NULL;
 		if(!user->assoc_list || !list_count(user->assoc_list))
 			continue;
 		
+		passwd_ptr = getpwnam(user->name);
+		if(passwd_ptr) 
+			user->uid = passwd_ptr->pw_uid;
+		else
+			user->uid = (uint32_t)NO_VAL;	
+
 		itr2 = list_iterator_create(user->assoc_list);
 		while((assoc = list_next(itr2))) {
+
 			if(!assoc->accounting_list
 			   || !list_count(assoc->accounting_list))
 				continue;
-
+			
 			while((local_cluster = list_next(cluster_itr))) {
 				if(!strcmp(local_cluster->name, 
 					   assoc->cluster)) {
-					ListIterator user_itr = 
-						list_iterator_create
+					ListIterator user_itr = NULL;
+					if(!group_accts) {
+						local_user = NULL;
+						goto new_user;
+					}
+					user_itr = list_iterator_create
 						(local_cluster->user_list); 
 					while((local_user 
 					       = list_next(user_itr))) {
-						if(!strcmp(local_user->name,
-							   assoc->user)) {
-							if(!group_accts &&
-							   !strcmp(local_user->
-								   name,
-								   assoc->
-								   user)) {
-								break;
-							} else if(group_accts)
-								break;
+						if(local_user->uid 
+						   == user->uid) {
+							break;
 						}
 					}
 					list_iterator_destroy(user_itr);
+				new_user:
 					if(!local_user) {
 						local_user = xmalloc(
 							sizeof
 							(local_user_rec_t));
 						local_user->name =
 							xstrdup(assoc->user);
+						local_user->uid =
+							user->uid;
 						local_user->acct_list =
 							list_create
 							(slurm_destroy_char);
+						list_append(local_cluster->
+							    user_list, 
+							    local_user);
 					}
 					break;
 				}
 			}
-			list_iterator_reset(cluster_itr);
 			if(!local_cluster) {
 				local_cluster = 
 					xmalloc(sizeof(local_cluster_rec_t));
@@ -375,12 +385,14 @@ extern int user_top(int argc, char *argv[])
 				local_user = 
 					xmalloc(sizeof(local_user_rec_t));
 				local_user->name = xstrdup(assoc->user);
+				local_user->uid = user->uid;
 				local_user->acct_list = 
 					list_create(slurm_destroy_char);
 				list_append(local_cluster->user_list, 
 					    local_user);
 			}
-			
+			list_iterator_reset(cluster_itr);
+
 			itr3 = list_iterator_create(local_user->acct_list);
 			while((object = list_next(itr3))) {
 				if(!strcmp(object, assoc->acct))
diff --git a/src/srun/allocate.c b/src/srun/allocate.c
index ca6091a28cbbdedeaa696099f62e16249d3f7c62..130f55e1a1d83a7bdd17bc57001da2498e59c4f1 100644
--- a/src/srun/allocate.c
+++ b/src/srun/allocate.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  * src/srun/allocate.c - srun functions for managing node allocations
- * $Id: allocate.c 14242 2008-06-11 23:29:49Z jette $
+ * $Id: allocate.c 14453 2008-07-08 20:26:18Z da $
  *****************************************************************************
  *  Copyright (C) 2002-2006 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -89,7 +89,7 @@ static sig_atomic_t destroy_job = 0;
 
 static void _set_pending_job_id(uint32_t job_id)
 {
-	info("Pending job allocation %u", job_id);
+	debug2("Pending job allocation %u", job_id);
 	pending_job_id = job_id;
 }
 
@@ -235,7 +235,7 @@ allocate_nodes(void)
 	xsignal(SIGUSR2, _signal_while_allocating);
 
 	while (!resp) {
-		resp = slurm_allocate_resources_blocking(j, opt.max_wait,
+		resp = slurm_allocate_resources_blocking(j, 0,
 							 _set_pending_job_id);
 		if (destroy_job) {
 			/* cancelled by signal */
diff --git a/src/srun/opt.c b/src/srun/opt.c
index 59d46290e06bdbbd2fa477fc5de71555a139614a..625c3ad469346730325c632743e461a5ab7fb5ec 100644
--- a/src/srun/opt.c
+++ b/src/srun/opt.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
  *  opt.c - options processing for srun
- *  $Id: opt.c 14110 2008-05-22 16:34:50Z jette $
+ *  $Id: opt.c 14420 2008-07-02 19:52:49Z jette $
  *****************************************************************************
  *  Copyright (C) 2002-2006 The Regents of the University of California.
  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
@@ -778,6 +778,7 @@ env_vars_t env_vars[] = {
 {"SLURM_OPEN_MODE",     OPT_OPEN_MODE,  NULL,               NULL             },
 {"SLURM_ACCTG_FREQ",    OPT_INT,        &opt.acctg_freq,    NULL             },
 {"SLURM_TASK_MEM",      OPT_INT,        &opt.task_mem,      NULL             },
+{"SLURM_NETWORK",       OPT_STRING,     &opt.network,       NULL             },
 {NULL, 0, NULL, NULL}
 };
 
@@ -1353,11 +1354,15 @@ static void set_options(const int argc, char **argv)
 				_get_int(optarg, "max-exit-timeout", true);
 			break;
 		case LONG_OPT_UID:
+			if (opt.euid != (uid_t) -1)
+				fatal ("duplicate --uid option");
 			opt.euid = uid_from_string (optarg);
 			if (opt.euid == (uid_t) -1)
 				fatal ("--uid=\"%s\" invalid", optarg);
 			break;
 		case LONG_OPT_GID:
+			if (opt.egid != (gid_t) -1)
+				fatal ("duplicate --gid option");
 			opt.egid = gid_from_string (optarg);
 			if (opt.egid == (gid_t) -1)
 				fatal ("--gid=\"%s\" invalid", optarg);
@@ -1388,9 +1393,7 @@ static void set_options(const int argc, char **argv)
 		case LONG_OPT_NETWORK:
 			xfree(opt.network);
 			opt.network = xstrdup(optarg);
-#ifdef HAVE_AIX
 			setenv("SLURM_NETWORK", opt.network, 1);
-#endif
 			break;
 		case LONG_OPT_PROPAGATE:
 			xfree(opt.propagate);
@@ -2012,9 +2015,6 @@ static bool _opt_verify(void)
 	if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid)) 
 		opt.gid = opt.egid;
 
-        if ((opt.egid != (gid_t) -1) && (opt.egid != opt.gid))
-	        opt.gid = opt.egid;
-
 	if (opt.propagate && parse_rlimits( opt.propagate, PROPAGATE_RLIMITS)) {
 		error( "--propagate=%s is not valid.", opt.propagate );
 		verified = false;
@@ -2221,7 +2221,7 @@ static void _usage(void)
 "            [--contiguous] [--mincpus=n] [--mem=MB] [--tmp=MB] [-C list]\n"
 "            [--mpi=type] [--account=name] [--dependency=type:jobid]\n"
 "            [--kill-on-bad-exit] [--propagate[=rlimits] [--comment=name]\n"
-"            [--cpu_bind=...] [--mem_bind=...]\n"
+"            [--cpu_bind=...] [--mem_bind=...] [--network=type]\n"
 "            [--ntasks-per-node=n] [--ntasks-per-socket=n]\n"
 "            [--ntasks-per-core=n]\n"
 #ifdef HAVE_BG		/* Blue gene specific options */
diff --git a/src/sview/block_info.c b/src/sview/block_info.c
index cc8e26892644f0bde1076baea7b82bfe88c5ffa2..9573169475cdcdba90d9380ad6c6bb83bf661080 100644
--- a/src/sview/block_info.c
+++ b/src/sview/block_info.c
@@ -1049,7 +1049,7 @@ display_it:
 				continue;
 			break;
 		default:
-			g_print("Unkown type %d\n", spec_info->type);
+			g_print("Unknown type %d\n", spec_info->type);
 			continue;
 		}
 		list_push(send_block_list, block_ptr);
diff --git a/src/sview/part_info.c b/src/sview/part_info.c
index ad0fb43e4152817632f0cfe2ad2972870a0f7165..8d181a4a107a2167477f974c5deecf99298cea62 100644
--- a/src/sview/part_info.c
+++ b/src/sview/part_info.c
@@ -2242,7 +2242,7 @@ display_it:
 				continue;
 			break;
 		default:
-			g_print("Unkown type %d\n", spec_info->type);
+			g_print("Unknown type %d\n", spec_info->type);
 			list_iterator_destroy(itr);
 			goto end_it;
 		}
diff --git a/testsuite/expect/test1.50 b/testsuite/expect/test1.50
index d04076e92f73bb3f8b0181b12cfa3131aceb965f..bccb6a3d285904deef854ff7bf8be8a49fb8f05a 100755
--- a/testsuite/expect/test1.50
+++ b/testsuite/expect/test1.50
@@ -58,7 +58,7 @@ expect {
 		set matches 1
 		 exp_continue
 	}
-	-re "job exceeded timelimit" {
+	-re "time limit exceeded" {
 		send_user "\nFAILURE: srun didn't terminate properly\n"
 		set exit_code 1
 		exp_continue
diff --git a/testsuite/expect/test1.7 b/testsuite/expect/test1.7
index 9bca53f859245f6edc19d11cb9e4b08b71367750..52b37442b87a11b68fcd21ea3dfe91d67464bf81 100755
--- a/testsuite/expect/test1.7
+++ b/testsuite/expect/test1.7
@@ -95,7 +95,7 @@ set timeout [expr $max_job_delay + $sleep_time]
 set timed_out 0
 set srun_pid [spawn $srun -t1 $bin_sleep $sleep_time]
 expect {
-	-re "job exceeded timelimit" {
+	-re "time limit exceeded" {
 		set timed_out 1
 		exp_continue
 	}
@@ -126,7 +126,7 @@ if {$timed_out == 1} {
 set completions 0
 set srun_pid [spawn $srun -t4 $bin_sleep $sleep_time]
 expect {
-	-re "job exceeded timelimit" {
+	-re "time limit exceeded" {
 		set completions -1
 		exp_continue
 	}
diff --git a/testsuite/expect/test1.8 b/testsuite/expect/test1.8
index e46a26558c8843dd288b7e981641434ebe23e5c6..3d68e60e38c36f3b2100d987289015fbfc5b0780 100755
--- a/testsuite/expect/test1.8
+++ b/testsuite/expect/test1.8
@@ -160,7 +160,7 @@ expect {
 		set exit_code 1
 		exp_continue
 	}
-	-re "job exceeded timelimit" {
+	-re "time limit exceeded" {
 		send_user "\nFAILURE: srun failed to complete\n"
 		set exit_code 1
 		exp_continue
diff --git a/testsuite/expect/test1.87 b/testsuite/expect/test1.87
index 53d5fc2063f120c9eedb06bb10206847c8cc2046..18a53d4537cc3f45e745d76bac6cf5913d72bfe4 100755
--- a/testsuite/expect/test1.87
+++ b/testsuite/expect/test1.87
@@ -80,7 +80,8 @@ expect {
 		exit 1
 	}
 	"$prompt" {
-		send_user "Job initiated\n"
+#		Printing this message seems to damage expect's buffers
+#		send_user "Job initiated\n"
 	}
 	timeout {
 		send_user "\nFAILURE: srun not responding\n"
@@ -124,7 +125,8 @@ expect {
 		exit 1
 	}
 	"$prompt" {
-		send_user "srun completed\n"
+#		Printing this message seems to damage expect's buffers
+#		send_user "srun completed\n"
 	}
 	timeout {
 		send_user "\nFAILURE: srun not responding\n"
@@ -196,7 +198,8 @@ expect {
 		exit 1
 	}
 	"$prompt" {
-		send_user "srun completed\n"
+#		Printing this message seems to damage expect's buffers
+#		send_user "srun completed\n"
 	}
 	timeout {
 		send_user "\nFAILURE: srun not responding\n"
@@ -247,7 +250,8 @@ expect {
 		exit 1
 	}
 	"$prompt" {
-		send_user "srun completed\n"
+#		Printing this message seems to damage expect's buffers
+#		send_user "srun completed\n"
 	}
 	timeout {
 		send_user "\nFAILURE: srun not responding\n"
@@ -285,7 +289,8 @@ expect {
 		exit 1
 	}
 	"$prompt" {
-		send_user "srun completed\n"
+#		Printing this message seems to damage expect's buffers
+#		send_user "srun completed\n"
 	}
 	timeout {
 		send_user "\nFAILURE: srun not responding\n"
diff --git a/testsuite/expect/test3.5 b/testsuite/expect/test3.5
index 3a41159da40cfd913fd4a7c54479eb85e7ffabc0..cdbff9e0952bed72aedc30ad68fe177bb4e94fe2 100755
--- a/testsuite/expect/test3.5
+++ b/testsuite/expect/test3.5
@@ -219,7 +219,7 @@ set sleep_time 300
 set timeout [expr $max_job_delay + $sleep_time]
 set srun_pid [spawn $srun -t1 -p $part_name $bin_sleep $sleep_time]
 expect {
-	-re "job exceeded timelimit" {
+	-re "time limit exceeded" {
 		set timed_out 1
 		exp_continue
 	}