diff --git a/NEWS b/NEWS
index 931281a8496283b0009e3986cd05dd59a5f08568..0333b3f6226b6540f652609d8099f89e212a1dba 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,10 @@
 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.1.0-pre6
+=============================
+ -- Added logic to "stat" a running job with sacct option -S use -j to specify
+    job.step 
 * Changes in SLURM 1.1.0-pre5
 =============================
  -- Added step completion RPC logic
diff --git a/src/common/forward.c b/src/common/forward.c
index cd4fddcd7fd0aaa3c6a1651272253f67716c03ac..de755a9e318af0baadb43afb5aae1d5e68773821 100644
--- a/src/common/forward.c
+++ b/src/common/forward.c
@@ -107,13 +107,16 @@ void *_forward_thread(void *arg)
 		ret_data_info->node_name = xstrdup(fwd_msg->node_name);
 		ret_data_info->nodeid = fwd_msg->header.srun_node_id;
 		for(i=0; i<fwd_msg->header.forward.cnt; i++) {
-			strncpy(name,
-				&fwd_msg->header.
-				forward.name[i * MAX_SLURM_NAME],
-				MAX_SLURM_NAME);
 			ret_data_info = xmalloc(sizeof(ret_data_info_t));
 			list_push(type->ret_data_list, ret_data_info);
-			ret_data_info->node_name = xstrdup(name);
+			if(fwd_msg->header.forward.name) {
+				strncpy(name,
+					&fwd_msg->header.
+					forward.name[i * MAX_SLURM_NAME],
+					MAX_SLURM_NAME);
+				ret_data_info->node_name = xstrdup(name);
+			} else 
+				ret_data_info->node_name = NULL;
 			ret_data_info->nodeid = 
 				fwd_msg->header.forward.node_id[i];
 		}
@@ -267,10 +270,13 @@ extern int forward_msg(forward_struct_t *forward_struct,
 		memcpy(&forward_msg->addr, 
 		       &header->forward.addr[i], 
 		       sizeof(slurm_addr));
-		strncpy(forward_msg->node_name,
-			&header->forward.name[i * MAX_SLURM_NAME],
-			MAX_SLURM_NAME);
-	        
+		if(header->forward.name) {
+			strncpy(forward_msg->node_name,
+				&header->forward.name[i * MAX_SLURM_NAME],
+				MAX_SLURM_NAME);
+	        } else 
+			memset(forward_msg->node_name, 0, MAX_SLURM_NAME);
+
 		forward_set(&forward_msg->header.forward,
 			    span[thr_count],
 			    &i,
@@ -315,7 +321,12 @@ extern int forward_set(forward_t *forward,
 	
 	if(span > 0) {
 		forward->addr = xmalloc(sizeof(slurm_addr) * span);
-		forward->name = xmalloc(sizeof(char) * (MAX_SLURM_NAME * span));
+		if(from->name)
+			forward->name = xmalloc(sizeof(char) 
+						* (MAX_SLURM_NAME * span));
+		else
+			forward->name = NULL;
+
 		forward->node_id = xmalloc(sizeof(int32_t) * span);
 		forward->timeout = from->timeout;
 		forward->init = FORWARD_INIT;
@@ -325,9 +336,10 @@ extern int forward_set(forward_t *forward,
 			       &from->addr[*pos+j],
 			       sizeof(slurm_addr));
 			//forward->addr[j-1] = forward_addr[*pos+j];
-			strncpy(&forward->name[(j-1) * MAX_SLURM_NAME], 
-				&from->name[(*pos+j) * MAX_SLURM_NAME], 
-				MAX_SLURM_NAME);
+			if(from->name)
+				strncpy(&forward->name[(j-1) * MAX_SLURM_NAME],
+					&from->name[(*pos+j) * MAX_SLURM_NAME],
+					MAX_SLURM_NAME);
 
 			if(from->node_id)
 				forward->node_id[j-1] = from->node_id[*pos+j];
@@ -345,6 +357,7 @@ extern int forward_set(forward_t *forward,
 		*pos += j;
 	} else {
 		forward_init(forward, NULL);
+		forward->timeout = from->timeout;
 	}
 	
 	return SLURM_SUCCESS;
@@ -385,8 +398,12 @@ extern int forward_set_launch(forward_t *forward,
 	
 	if(span > 0) {
 		forward->addr = xmalloc(sizeof(slurm_addr) * span);
-		forward->name = 
-			xmalloc(sizeof(char) * (MAX_SLURM_NAME * span));
+		if(step_layout->host)
+			forward->name = 
+				xmalloc(sizeof(char) 
+					* (MAX_SLURM_NAME * span));
+		else
+			forward->name = NULL;
 		forward->node_id = xmalloc(sizeof(int32_t) * span);
 		forward->timeout = timeout;
 		forward->init = FORWARD_INIT;
@@ -407,9 +424,10 @@ extern int forward_set_launch(forward_t *forward,
 			       &slurmd_addr[i], 
 			       sizeof(slurm_addr));
 			//forward->addr[j-1] = slurmd_addr[i];
-			strncpy(&forward->name[(j-1) * MAX_SLURM_NAME], 
-				step_layout->host[*pos+j], 
-				MAX_SLURM_NAME);
+			if(step_layout->host)
+				strncpy(&forward->name[(j-1) * MAX_SLURM_NAME],
+					step_layout->host[*pos+j], 
+					MAX_SLURM_NAME);
 			forward->node_id[j-1] = (*pos+j);
 			/* strncpy(name, */
 /* 				step_layout->host[*pos+j], */
@@ -423,6 +441,7 @@ extern int forward_set_launch(forward_t *forward,
 		*pos += j;
 	} else {
 		forward_init(forward, NULL);
+		forward->timeout = timeout;
 	}
 
 	return SLURM_SUCCESS;
@@ -446,11 +465,16 @@ extern int no_resp_forwards(forward_t *forward, List *ret_list, int err)
 	type->err = err;
 	type->ret_data_list = list_create(destroy_data_info);
 	for(i=0; i<forward->cnt; i++) {
-		strncpy(name, 
-			&forward->name[i * MAX_SLURM_NAME], MAX_SLURM_NAME);
 		ret_data_info = xmalloc(sizeof(ret_data_info_t));
 		list_push(type->ret_data_list, ret_data_info);
-		ret_data_info->node_name = xstrdup(name);
+		if(forward->name) {
+			strncpy(name, 
+				&forward->name[i * MAX_SLURM_NAME], 
+				MAX_SLURM_NAME);
+			ret_data_info->node_name = xstrdup(name);
+		} else 
+			ret_data_info->node_name = NULL;
+	      	
 		ret_data_info->nodeid = forward->node_id[i];
 	}
 no_forward:
diff --git a/src/common/slurm_jobacct.c b/src/common/slurm_jobacct.c
index 759a98b33b39ab17567b7cee40b33b7354167d40..00c41c458eadd422c40cac75b7400c9ab33d8938 100644
--- a/src/common/slurm_jobacct.c
+++ b/src/common/slurm_jobacct.c
@@ -72,6 +72,8 @@ typedef struct slurm_jobacct_ops {
 				       void *data);
 	void (*jobacct_aggregate)     (jobacctinfo_t *dest, 
 				       jobacctinfo_t *from);
+	void (*jobacct_2_sacct)       (sacct_t *sacct, 
+				       jobacctinfo_t *jobacct);
 	void (*jobacct_pack)          (jobacctinfo_t *jobacct, Buf buffer);
 	int (*jobacct_unpack)         (jobacctinfo_t **jobacct, Buf buffer);
 	int (*jobacct_init)	      (char *job_acct_log);
@@ -173,6 +175,7 @@ _slurm_jobacct_get_ops( slurm_jobacct_context_t c )
 		"jobacct_p_setinfo",
 		"jobacct_p_getinfo",
 		"jobacct_p_aggregate",
+		"jobacct_p_2_sacct",
 		"jobacct_p_pack",
 		"jobacct_p_unpack",	
 		"jobacct_p_init_slurmctld",
@@ -359,6 +362,18 @@ extern void jobacct_g_aggregate(jobacctinfo_t *dest, jobacctinfo_t *from)
 	return;
 }
 
+extern void jobacct_g_2_sacct(sacct_t *sacct, jobacctinfo_t *jobacct)
+{
+	if (_slurm_jobacct_init() < 0)
+		return;
+	
+	slurm_mutex_lock( &g_jobacct_context_lock );
+	if ( g_jobacct_context )
+		(*(g_jobacct_context->ops.jobacct_2_sacct))(sacct, jobacct);
+	slurm_mutex_unlock( &g_jobacct_context_lock );	
+	return;
+}
+
 extern void jobacct_g_pack(jobacctinfo_t *jobacct, Buf buffer)
 {
 	if (_slurm_jobacct_init() < 0)
diff --git a/src/common/slurm_jobacct.h b/src/common/slurm_jobacct.h
index a04c6986c3e7a31d75ae35ad4e88e98e7a3fd205..eaff1b2934aa944fd5d0fbf24fcf885d9c5012a5 100644
--- a/src/common/slurm_jobacct.h
+++ b/src/common/slurm_jobacct.h
@@ -52,8 +52,9 @@
 
 #include "src/slurmd/slurmstepd/slurmstepd_job.h"
 #include "src/slurmctld/slurmctld.h"
+#include "src/sacct/sacct_stat.h"
 
-typedef struct slurm_jobacct_context * slurm_jobacct_context_t;
+typedef struct slurm_jobacct_context *slurm_jobacct_context_t;
 
 /* common */
 extern int jobacct_g_init_struct(jobacctinfo_t *jobacct, uint16_t tid);
@@ -64,6 +65,7 @@ extern int jobacct_g_setinfo(jobacctinfo_t *jobacct,
 extern int jobacct_g_getinfo(jobacctinfo_t *jobacct, 
 			     enum jobacct_data_type type, void *data);
 extern void jobacct_g_aggregate(jobacctinfo_t *dest, jobacctinfo_t *from);
+extern void jobacct_g_2_sacct(sacct_t *sacct, jobacctinfo_t *jobacct);
 extern void jobacct_g_pack(jobacctinfo_t *jobacct, Buf buffer);
 extern int jobacct_g_unpack(jobacctinfo_t **jobacct, Buf buffer);
 
diff --git a/src/common/slurm_protocol_defs.c b/src/common/slurm_protocol_defs.c
index e8d5180d58a5e6e841ca1626ce6ee6f7d43171e1..909fc5d9ded12f7278fb8fedbca2148096086a64 100644
--- a/src/common/slurm_protocol_defs.c
+++ b/src/common/slurm_protocol_defs.c
@@ -939,3 +939,11 @@ extern void slurm_free_step_complete_msg(step_complete_msg_t *msg)
 		xfree(msg);
 	}
 }
+
+extern void slurm_free_stat_jobacct_msg(stat_jobacct_msg_t *msg)
+{
+	if (msg) {
+		jobacct_g_free(msg->jobacct);
+		xfree(msg);
+	}
+}
diff --git a/src/common/slurm_protocol_defs.h b/src/common/slurm_protocol_defs.h
index b52b70ed4f3495b09dd6c7e178d50eb5d9b9b0d7..fbb2b2d63d9ad6c87eb21280e91393be965b1522 100644
--- a/src/common/slurm_protocol_defs.h
+++ b/src/common/slurm_protocol_defs.h
@@ -144,7 +144,8 @@ typedef enum {
 	REQUEST_STEP_COMPLETE,
 	REQUEST_COMPLETE_JOB_ALLOCATION,
 	REQUEST_COMPLETE_BATCH_SCRIPT,
-
+	MESSAGE_STAT_JOBACCT,
+	
 	REQUEST_LAUNCH_TASKS = 6001,
 	RESPONSE_LAUNCH_TASKS,
 	MESSAGE_TASK_EXIT,
@@ -324,6 +325,13 @@ typedef struct step_complete_msg {
 	jobacctinfo_t *jobacct;
 } step_complete_msg_t;
 
+typedef struct stat_jobacct_msg {
+	uint32_t job_id;
+	uint32_t step_id;
+	uint32_t num_tasks;
+	jobacctinfo_t *jobacct;
+} stat_jobacct_msg_t;
+
 typedef struct kill_tasks_msg {
 	uint32_t job_id;
 	uint32_t job_step_id;
@@ -674,6 +682,7 @@ void slurm_free_partition_info_msg(partition_info_msg_t * msg);
 void slurm_free_get_kvs_msg(kvs_get_msg_t *msg);
 void inline slurm_free_file_bcast_msg(file_bcast_msg_t *msg);
 void inline slurm_free_step_complete_msg(step_complete_msg_t *msg);
+void inline slurm_free_stat_jobacct_msg(stat_jobacct_msg_t *msg);
 
 extern char *job_reason_string(enum job_wait_reason inx);
 extern char *job_state_string(enum job_states inx);
diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c
index d2d6637b0ed3d0bab7f7d4171c14372b41321839..c0532e2a86b4355fd0139463cec3ec0d534f3c72 100644
--- a/src/common/slurm_protocol_pack.c
+++ b/src/common/slurm_protocol_pack.c
@@ -206,6 +206,10 @@ static void _pack_complete_batch_script_msg(
 	complete_batch_script_msg_t * msg, Buf buffer);
 static int _unpack_complete_batch_script_msg(
 	complete_batch_script_msg_t ** msg_ptr, Buf buffer);
+
+static void _pack_stat_jobacct_msg(stat_jobacct_msg_t * msg, Buf buffer);
+static int _unpack_stat_jobacct_msg(stat_jobacct_msg_t ** msg_ptr, Buf buffer);
+
 static void _pack_step_complete_msg(step_complete_msg_t * msg,
 				    Buf buffer);
 static int _unpack_step_complete_msg(step_complete_msg_t **
@@ -516,6 +520,10 @@ pack_msg(slurm_msg_t const *msg, Buf buffer)
 		 _pack_step_complete_msg((step_complete_msg_t *)msg->data,
 					 buffer);
 		 break;
+	 case MESSAGE_STAT_JOBACCT:
+		 _pack_stat_jobacct_msg((stat_jobacct_msg_t *) msg->data, 
+					buffer);
+		 break;
 	 case REQUEST_SIGNAL_JOB:
 		 _pack_signal_job_msg((signal_job_msg_t *) msg->data, buffer);
 		 break;
@@ -789,6 +797,10 @@ unpack_msg(slurm_msg_t * msg, Buf buffer)
 						 **) & (msg->data),
 						buffer);
 		 break;
+	 case MESSAGE_STAT_JOBACCT:
+		 rc = _unpack_stat_jobacct_msg(
+			 (stat_jobacct_msg_t **) &(msg->data), buffer);
+		 break;
 	 case REQUEST_SIGNAL_JOB:
 		 rc = _unpack_signal_job_msg((signal_job_msg_t **)&(msg->data),
 					     buffer);
@@ -2797,6 +2809,38 @@ _unpack_complete_batch_script_msg(
 	return SLURM_ERROR;
 }
 
+static void 
+_pack_stat_jobacct_msg(stat_jobacct_msg_t * msg, Buf buffer)
+{
+	pack32((uint32_t)msg->job_id, buffer);
+	pack32((uint32_t)msg->step_id, buffer);
+	pack32((uint32_t)msg->num_tasks, buffer);
+	jobacct_g_pack(msg->jobacct, buffer);	
+}
+
+
+static int 
+_unpack_stat_jobacct_msg(stat_jobacct_msg_t ** msg_ptr, Buf buffer)
+{
+	stat_jobacct_msg_t *msg;
+	
+	msg = xmalloc(sizeof(stat_jobacct_msg_t));
+	*msg_ptr = msg;	
+
+	safe_unpack32(&msg->job_id, buffer);
+	safe_unpack32(&msg->step_id, buffer);
+	safe_unpack32(&msg->num_tasks, buffer);
+	jobacct_g_unpack(&msg->jobacct, buffer);
+
+	return SLURM_SUCCESS;
+
+unpack_error:
+	xfree(msg);
+	*msg_ptr = NULL;
+	return SLURM_ERROR;
+
+}
+
 static void 
 _pack_step_complete_msg(step_complete_msg_t * msg, Buf buffer)
 {
diff --git a/src/plugins/jobacct/aix/jobacct_aix.c b/src/plugins/jobacct/aix/jobacct_aix.c
index f1b17ae5086ef9ba476a11c4ebe01ad5822acb15..f3269d70bf1cb5e7957a5c8ed820d872d08831be 100644
--- a/src/plugins/jobacct/aix/jobacct_aix.c
+++ b/src/plugins/jobacct/aix/jobacct_aix.c
@@ -121,6 +121,11 @@ void jobacct_p_aggregate(struct jobacctinfo *dest, struct jobacctinfo *from)
 	common_aggregate(dest, from);
 }
 
+void jobacct_p_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct)
+{
+	common_2_sacct(sacct, jobacct);
+}
+
 void jobacct_p_pack(struct jobacctinfo *jobacct, Buf buffer)
 {
 	common_pack(jobacct, buffer);
diff --git a/src/plugins/jobacct/bluegene/jobacct_bluegene.c b/src/plugins/jobacct/bluegene/jobacct_bluegene.c
index 2350ff99a86674619253a770167bc163612d1b12..3705f778d80e7943ae71da9d23be6051a73ef1d9 100644
--- a/src/plugins/jobacct/bluegene/jobacct_bluegene.c
+++ b/src/plugins/jobacct/bluegene/jobacct_bluegene.c
@@ -124,6 +124,11 @@ void jobacct_p_aggregate(struct jobacctinfo *dest, struct jobacctinfo *from)
 	common_aggregate(dest, from);
 }
 
+void jobacct_p_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct)
+{
+	common_2_sacct(sacct, jobacct);
+}
+
 void jobacct_p_pack(struct jobacctinfo *jobacct, Buf buffer)
 {
 	common_pack(jobacct, buffer);
diff --git a/src/plugins/jobacct/common/common_slurmstepd.c b/src/plugins/jobacct/common/common_slurmstepd.c
index 62184d75392dcaa9c5da41fe02c4d3001bb1a7d1..afcca62925dc658c95d8ffcc1d36f9f92f2e6896 100644
--- a/src/plugins/jobacct/common/common_slurmstepd.c
+++ b/src/plugins/jobacct/common/common_slurmstepd.c
@@ -78,12 +78,10 @@ extern struct jobacctinfo *common_stat_task(pid_t pid)
 		if(jobacct->pid == pid)
 			break;
 	}
-	slurm_mutex_unlock(&jobacct_lock);
 	list_iterator_destroy(itr);
-	
-	return jobacct;
+	slurm_mutex_unlock(&jobacct_lock);
 error:
-	return NULL;
+	return jobacct;
 }
 
 extern int common_remove_task(pid_t pid)
diff --git a/src/plugins/jobacct/common/jobacct_common.c b/src/plugins/jobacct/common/jobacct_common.c
index af562e86f52a68b4c39041dcfb1cde32128d91f1..1b73f38d6822bcb2d15b40a7dd3c8ac2c6038c6b 100644
--- a/src/plugins/jobacct/common/jobacct_common.c
+++ b/src/plugins/jobacct/common/jobacct_common.c
@@ -220,6 +220,9 @@ rwfail:
 extern void common_aggregate(struct jobacctinfo *dest, 
 			     struct jobacctinfo *from)
 {
+	xassert(dest);
+	xassert(from);
+
 	slurm_mutex_lock(&jobacct_lock);
 	if(dest->max_vsize < from->max_vsize) {
 		dest->max_vsize = from->max_vsize;
@@ -291,8 +294,37 @@ extern void common_aggregate(struct jobacctinfo *dest,
 	slurm_mutex_unlock(&jobacct_lock);	
 }
 
+extern void common_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct)
+{
+	xassert(jobacct);
+	xassert(sacct);
+	slurm_mutex_lock(&jobacct_lock);
+	sacct->max_vsize = jobacct->max_vsize;
+	sacct->max_vsize_task = jobacct->max_vsize_task;
+	sacct->ave_vsize = jobacct->tot_vsize;
+	sacct->max_rss = jobacct->max_rss;
+	sacct->max_rss_task = jobacct->max_rss_task;
+	sacct->ave_rss = jobacct->tot_rss;
+	sacct->max_pages = jobacct->max_pages;
+	sacct->max_pages_task = jobacct->max_pages_task;
+	sacct->ave_pages = jobacct->tot_pages;
+	sacct->min_cpu = jobacct->min_cpu;
+	sacct->min_cpu_task = jobacct->min_cpu_task;
+	sacct->ave_cpu = jobacct->tot_cpu;
+	slurm_mutex_unlock(&jobacct_lock);
+}
+
 extern void common_pack(struct jobacctinfo *jobacct, Buf buffer)
 {
+	int i=0;
+
+	if(!jobacct) {
+		for(i=0; i<26; i++)
+			pack32((uint32_t) 0, buffer);
+		for(i=0; i<4; i++)
+			pack16((uint16_t) 0, buffer);
+		return;
+	} 
 	slurm_mutex_lock(&jobacct_lock);
 	pack32((uint32_t)jobacct->rusage.ru_utime.tv_sec, buffer);
 	pack32((uint32_t)jobacct->rusage.ru_utime.tv_usec, buffer);
@@ -313,17 +345,17 @@ extern void common_pack(struct jobacctinfo *jobacct, Buf buffer)
 	pack32((uint32_t)jobacct->rusage.ru_nvcsw, buffer);
 	pack32((uint32_t)jobacct->rusage.ru_nivcsw, buffer);
 	pack32((uint32_t)jobacct->max_vsize, buffer);
-	pack16((uint16_t)jobacct->max_vsize_task, buffer);
 	pack32((uint32_t)jobacct->tot_vsize, buffer);
 	pack32((uint32_t)jobacct->max_rss, buffer);
-	pack16((uint16_t)jobacct->max_rss_task, buffer);
 	pack32((uint32_t)jobacct->tot_rss, buffer);
 	pack32((uint32_t)jobacct->max_pages, buffer);
-	pack16((uint16_t)jobacct->max_pages_task, buffer);
 	pack32((uint32_t)jobacct->tot_pages, buffer);
 	pack32((uint32_t)jobacct->min_cpu, buffer);
-	pack16((uint16_t)jobacct->min_cpu_task, buffer);
 	pack32((uint32_t)jobacct->tot_cpu, buffer);
+	pack16((uint16_t)jobacct->max_vsize_task, buffer);
+	pack16((uint16_t)jobacct->max_rss_task, buffer);
+	pack16((uint16_t)jobacct->max_pages_task, buffer);
+	pack16((uint16_t)jobacct->min_cpu_task, buffer);
 	slurm_mutex_unlock(&jobacct_lock);
 }
 
@@ -369,17 +401,17 @@ extern int common_unpack(struct jobacctinfo **jobacct, Buf buffer)
 	safe_unpack32(&uint32_tmp, buffer);
 	(*jobacct)->rusage.ru_nivcsw = uint32_tmp;
 	safe_unpack32(&(*jobacct)->max_vsize, buffer);
-	safe_unpack16(&(*jobacct)->max_vsize_task, buffer);
 	safe_unpack32(&(*jobacct)->tot_vsize, buffer);
 	safe_unpack32(&(*jobacct)->max_rss, buffer);
-	safe_unpack16(&(*jobacct)->max_rss_task, buffer);
 	safe_unpack32(&(*jobacct)->tot_rss, buffer);
 	safe_unpack32(&(*jobacct)->max_pages, buffer);
-	safe_unpack16(&(*jobacct)->max_pages_task, buffer);
 	safe_unpack32(&(*jobacct)->tot_pages, buffer);
 	safe_unpack32(&(*jobacct)->min_cpu, buffer);
-	safe_unpack16(&(*jobacct)->min_cpu_task, buffer);
 	safe_unpack32(&(*jobacct)->tot_cpu, buffer);
+	safe_unpack16(&(*jobacct)->max_vsize_task, buffer);
+	safe_unpack16(&(*jobacct)->max_rss_task, buffer);
+	safe_unpack16(&(*jobacct)->max_pages_task, buffer);
+	safe_unpack16(&(*jobacct)->min_cpu_task, buffer);
 	return SLURM_SUCCESS;
 
       unpack_error:
diff --git a/src/plugins/jobacct/common/jobacct_common.h b/src/plugins/jobacct/common/jobacct_common.h
index c23b58b7d2d350620fa3b1554b310d03c56725eb..4c738607140d1b42c05554a9f61283bbe29db45b 100644
--- a/src/plugins/jobacct/common/jobacct_common.h
+++ b/src/plugins/jobacct/common/jobacct_common.h
@@ -49,6 +49,7 @@
 #include "src/common/list.h"
 #include "src/common/xstring.h"
 #include "src/common/node_select.h"
+
 #include <ctype.h>
 
 #define BUFFER_SIZE 4096
@@ -91,6 +92,7 @@ extern int common_getinfo(struct jobacctinfo *jobacct,
 			  enum jobacct_data_type type, void *data);
 extern void common_aggregate(struct jobacctinfo *dest, 
 			     struct jobacctinfo *from);
+extern void common_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct);
 extern void common_pack(struct jobacctinfo *jobacct, Buf buffer);
 extern int common_unpack(struct jobacctinfo **jobacct, Buf buffer);
 
diff --git a/src/plugins/jobacct/linux/jobacct_linux.c b/src/plugins/jobacct/linux/jobacct_linux.c
index 3072648a9b41ed355b8cea3f2b0e033a092486a4..f4c69c9d9781242e335e43854ee70c64e551c262 100644
--- a/src/plugins/jobacct/linux/jobacct_linux.c
+++ b/src/plugins/jobacct/linux/jobacct_linux.c
@@ -123,6 +123,11 @@ void jobacct_p_aggregate(struct jobacctinfo *dest, struct jobacctinfo *from)
 	common_aggregate(dest, from);
 }
 
+void jobacct_p_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct)
+{
+	common_2_sacct(sacct, jobacct);
+}
+
 void jobacct_p_pack(struct jobacctinfo *jobacct, Buf buffer)
 {
 	common_pack(jobacct, buffer);
@@ -231,6 +236,7 @@ int jobacct_p_add_task(pid_t pid, uint16_t tid)
 
 struct jobacctinfo *jobacct_p_stat_task(pid_t pid)
 {
+	_get_process_data();
 	return common_stat_task(pid);
 }
 
diff --git a/src/plugins/jobacct/none/jobacct_none.c b/src/plugins/jobacct/none/jobacct_none.c
index b3c16025186df7835f1842ff58ec058555d8e934..2f6846da8623d333cc2cb8afbcf4484cd67f1144 100644
--- a/src/plugins/jobacct/none/jobacct_none.c
+++ b/src/plugins/jobacct/none/jobacct_none.c
@@ -120,6 +120,11 @@ void jobacct_p_aggregate(struct jobacctinfo *dest, struct jobacctinfo *from)
 	return;
 }
 
+void jobacct_p_2_sacct(sacct_t *sacct, struct jobacctinfo *jobacct)
+{
+	return;
+}
+
 void jobacct_p_pack(struct jobacctinfo *jobacct, Buf buffer)
 {
 	return;
diff --git a/src/sacct/Makefile.am b/src/sacct/Makefile.am
index 0866bd7433631972b535e3c1aa61186219761edc..c5e5579c059498335865210fdc3b48e480379057 100644
--- a/src/sacct/Makefile.am
+++ b/src/sacct/Makefile.am
@@ -12,7 +12,7 @@ sacct_LDADD =					\
 	$(top_builddir)/src/api/libslurm.la
 
 noinst_HEADERS = sacct.c 
-sacct_SOURCES = sacct.c process.c print.c options.c
+sacct_SOURCES = sacct.c process.c print.c options.c sacct_stat.c
 
 force:
 $(sacct_LDADD) : force
diff --git a/src/sacct/options.c b/src/sacct/options.c
index 2cd3a62f0c2c8b1b1aa3c61dc406c9b38f13e088..ea30561b78fb92636d9970ff403b529143ee5441 100644
--- a/src/sacct/options.c
+++ b/src/sacct/options.c
@@ -204,13 +204,13 @@ void _help_msg(void)
 	       "    accounting log file to refer to different jobs; such jobs\n"
 	       "    can be distinguished by the \"job_start\" time stamp in the\n"
 	       "    data records.\n"
-	       "      When data for specific jobs or jobsteps are requested with\n"
-	       "    the --jobs or --jobsteps options, we assume that the user\n"
+	       "      When data for specific jobs are requested with\n"
+	       "    the --jobs option, we assume that the user\n"
 	       "    wants to see only the most recent job with that number. This\n"
 	       "    behavior can be overridden by specifying --duplicates, in\n"
 	       "    which case all records that match the selection criteria\n"
 	       "    will be returned.\n"
-	       "      When neither --jobs or --jobsteps is specified, we report\n"
+	       "      When --jobs is not specified, we report\n"
 	       "    data for all jobs that match the selection criteria, even if\n"
 	       "    some of the job numbers are reused. Specify that you only\n"
 	       "    want the most recent job for each selected job number with\n"
@@ -245,11 +245,10 @@ void _help_msg(void)
 	       "--help-fields\n"
 	       "    Print a list of fields that can be specified with the\n"
 	       "    \"--fields\" option\n"
-	       "-j <job_list>, --jobs=<job_list>\n"
+	       "-j <job(.step)>, --jobs=<job(.step)>\n"
 	       "    Display information about this job or comma-separated\n"
-	       "    list of jobs. The default is all jobs.\n"
-	       "-J <job.step>, --jobstep=<job.step>\n"
-	       "    Show data only for the specified step of the specified job.\n"
+	       "    list of jobs. The default is all jobs. Adding .step will\n"
+	       "    display the specfic job step of that job.\n"
 	       "--noduplicates\n"
 	       "    See the discussion under --duplicates.\n"
 	       "--noheader\n"
@@ -291,6 +290,7 @@ void _init_params()
 	params.opt_dump = 0;		/* --dump */
 	params.opt_dup = -1;		/* --duplicates; +1 = explicitly set */
 	params.opt_fdump = 0;		/* --formattted_dump */
+	params.opt_stat = 0;		/* --stat */
 	params.opt_gid = -1;		/* --gid (-1=wildcard, 0=root) */
 	params.opt_header = 1;		/* can only be cleared */
 	params.opt_help = 0;		/* --help */
@@ -304,7 +304,6 @@ void _init_params()
 	params.opt_field_list = NULL;	/* --fields= */
 	params.opt_filein = NULL;	/* --file */
 	params.opt_job_list = NULL;	/* --jobs */
-	params.opt_jobstep_list = NULL;	/* --jobstep */
 	params.opt_partition_list = NULL;/* --partitions */
 	params.opt_state_list = NULL;	/* --states */
 }
@@ -416,6 +415,7 @@ int get_data(void)
 	selected_step_t *selected_step = NULL;
 	char *selected_part = NULL;
 	ListIterator itr = NULL;
+	int show_full = 0;
 
 	fd = _open_log_file();
 	
@@ -448,11 +448,14 @@ int get_data(void)
 			while((selected_step = list_next(itr))) {
 				if (strcmp(selected_step->job, f[F_JOB]))
 					continue;
-				/* job matches; does the step> */
-				if (selected_step->step == NULL
-				    || rec_type == JOB_STEP 
-				    || !strcmp(f[F_JOBSTEP], 
-					       selected_step->step)) {
+				/* job matches; does the step? */
+				if(selected_step->step == NULL) {
+					show_full = 1;
+					list_iterator_destroy(itr);
+					goto foundjob;
+				} else if (rec_type == JOB_STEP 
+					   || !strcmp(f[F_JOBSTEP], 
+						      selected_step->step)) {
 					list_iterator_destroy(itr);
 					goto foundjob;
 				}
@@ -487,28 +490,28 @@ int get_data(void)
 				printf("Bad data on a Job Start\n");
 				_show_rec(f);
 			} else 
-				process_start(f, lc);
+				process_start(f, lc, show_full);
 			break;
 		case JOB_STEP:
 			if(i < JOB_STEP_LENGTH) {
 				printf("Bad data on a Step entry\n");
 				_show_rec(f);
 			} else
-				process_step(f, lc);
+				process_step(f, lc, show_full);
 			break;
 		case JOB_SUSPEND:
 			if(i < JOB_TERM_LENGTH) {
 				printf("Bad data on a Suspend entry\n");
 				_show_rec(f);
 			} else
-				process_suspend(f, lc);
+				process_suspend(f, lc, show_full);
 			break;
 		case JOB_TERMINATED:
 			if(i < JOB_TERM_LENGTH) {
 				printf("Bad data on a Job Term\n");
 				_show_rec(f);
 			} else
-				process_terminated(f, lc);
+				process_terminated(f, lc, show_full);
 			break;
 		default:
 			if (params.opt_verbose > 1)
@@ -536,10 +539,12 @@ void parse_command_line(int argc, char **argv)
 {
 	extern int optind;
 	int c, i, optionIndex = 0;
-	char *end, *start, *acct_type;
+	char *end = NULL, *start = NULL, *acct_type = NULL;
 	selected_step_t *selected_step = NULL;
 	ListIterator itr = NULL;
 	struct stat stat_buf;
+	char *dot = NULL;
+
 	static struct option long_options[] = {
 		{"all", 0,0, 'a'},
 		{"brief", 0, 0, 'b'},
@@ -549,12 +554,12 @@ void parse_command_line(int argc, char **argv)
 		{"fields", 1, 0, 'F'},
 		{"file", 1, 0, 'f'},
 		{"formatted_dump", 0, 0, 'O'},
+		{"stat", 0, 0, 'S'},
 		{"gid", 1, 0, 'g'},
 		{"group", 1, 0, 'g'},
 		{"help", 0, &params.opt_help, 1},
 		{"help-fields", 0, &params.opt_help, 2},
 		{"jobs", 1, 0, 'j'},
-		{"jobstep", 1, 0, 'J'},
 		{"long", 0, 0, 'l'},
 		{"big_logfile", 0, &params.opt_lowmem, 1},
 		{"noduplicates", 0, &params.opt_dup, 0},
@@ -578,7 +583,7 @@ void parse_command_line(int argc, char **argv)
 	opterr = 1;		/* Let getopt report problems to the user */
 
 	while (1) {		/* now cycle through the command line */
-		c = getopt_long(argc, argv, "abde:F:f:g:hj:J:lOPp:s:tUu:Vv",
+		c = getopt_long(argc, argv, "abde:F:f:g:hj:J:lOPp:s:StUu:Vv",
 				long_options, &optionIndex);
 		if (c == -1)
 			break;
@@ -683,7 +688,9 @@ void parse_command_line(int argc, char **argv)
 			break;
 
 		case 'j':
-			if (strspn(optarg, "0123456789, ") < strlen(optarg)) {
+			if ((strspn(optarg, "0123456789, ") < strlen(optarg))
+			    && (strspn(optarg, ".0123456789, ") 
+				< strlen(optarg))) {
 				fprintf(stderr, "Invalid jobs list: %s\n",
 					optarg);
 				exit(1);
@@ -697,21 +704,6 @@ void parse_command_line(int argc, char **argv)
 			strcat(params.opt_job_list, ",");
 			break;
 
-		case 'J':
-			if (strspn(optarg, ".0123456789, ") < strlen(optarg)) {
-				fprintf(stderr, "Invalid jobstep list: %s\n",
-					optarg);
-				exit(1);
-			}
-			params.opt_jobstep_list =
-				xrealloc(params.opt_jobstep_list,
-					 (params.opt_jobstep_list==NULL? 0 :
-					  strlen(params.opt_jobstep_list)) +
-					 strlen(optarg) + 1);
-			strcat(params.opt_jobstep_list, optarg);
-			strcat(params.opt_jobstep_list, ",");
-			break;
-
 		case 'l':
 			params.opt_field_list =
 				xrealloc(params.opt_field_list,
@@ -750,6 +742,10 @@ void parse_command_line(int argc, char **argv)
 			strcat(params.opt_state_list, ",");
 			break;
 
+		case 'S':
+			params.opt_stat = 1;
+			break;
+
 		case 't':
 			params.opt_total = 1;
 			break;
@@ -805,7 +801,7 @@ void parse_command_line(int argc, char **argv)
 
 	/* Now set params.opt_dup, unless they've already done so */
 	if (params.opt_dup < 0)	/* not already set explicitly */
-		if (params.opt_job_list || params.opt_jobstep_list)
+		if (params.opt_job_list)
 			/* They probably want the most recent job N if
 			 * they requested specific jobs or steps. */
 			params.opt_dup = 0;
@@ -816,12 +812,12 @@ void parse_command_line(int argc, char **argv)
 			"\topt_dup=%d\n"
 			"\topt_expire=%s (%lu seconds)\n"
 			"\topt_fdump=%d\n"
+			"\topt_stat=%d\n"
 			"\topt_field_list=%s\n"
 			"\topt_filein=%s\n"
 			"\topt_header=%d\n"
 			"\topt_help=%d\n"
 			"\topt_job_list=%s\n"
-			"\topt_jobstep_list=%s\n"
 			"\topt_long=%d\n"
 			"\topt_lowmem=%d\n"
 			"\topt_partition_list=%s\n"
@@ -834,12 +830,12 @@ void parse_command_line(int argc, char **argv)
 			params.opt_dup,
 			params.opt_expire_timespec, params.opt_expire,
 			params.opt_fdump,
+			params.opt_stat,
 			params.opt_field_list,
 			params.opt_filein,
 			params.opt_header,
 			params.opt_help,
 			params.opt_job_list,
-			params.opt_jobstep_list,
 			params.opt_long,
 			params.opt_lowmem,
 			params.opt_partition_list,
@@ -880,61 +876,39 @@ void parse_command_line(int argc, char **argv)
 		}
 	}
 
-	/* specific jobsteps requested? */
-	if (params.opt_jobstep_list) {
-		char *dot;
-
-		start = params.opt_jobstep_list;
-		while ((end = strstr(start, ","))) {
-			*end = 0;;
-			while (isspace(*start))
-				start++;	/* discard whitespace */
-			dot = strstr(start, ".");
-			if (dot == NULL) {
-				fprintf(stderr, "Invalid jobstep: %s\n",
-					start);
-				exit(1);
-			}
-			*dot++ = 0;
-			selected_step = xmalloc(sizeof(selected_step_t));
-			list_append(selected_steps, selected_step);
-			
-			selected_step->job = xstrdup(start);
-			selected_step->step = xstrdup(dot);
-			start = end + 1;
-		}
-		if (params.opt_verbose) {
-			fprintf(stderr, "Job steps requested:\n");
-			itr = list_iterator_create(selected_steps);
-			while((selected_step = list_next(itr))) 
-				fprintf(stderr, "\t: %s.%s\n",
-					selected_step->job,
-					selected_step->step);
-			list_iterator_destroy(itr);
-			
-		}
-	}
-
 	/* specific jobs requested? */
 	if (params.opt_job_list) { 
 		start = params.opt_job_list;
 		while ((end = strstr(start, ","))) {
+			*end = 0;
 			while (isspace(*start))
 				start++;	/* discard whitespace */
-			*end = 0;
 			selected_step = xmalloc(sizeof(selected_step_t));
 			list_append(selected_steps, selected_step);
 			
 			selected_step->job = xstrdup(start);
-			selected_step->step = NULL;
+			dot = strstr(start, ".");
+			if (dot == NULL) {
+				debug2("No jobstep requested");
+				selected_step->step = NULL;
+			} else {
+				*dot++ = 0;
+				selected_step->step = xstrdup(dot);
+			}
 			start = end + 1;
 		}
 		if (params.opt_verbose) {
 			fprintf(stderr, "Jobs requested:\n");
 			itr = list_iterator_create(selected_steps);
-			while((selected_step = list_next(itr))) 
-				fprintf(stderr, "\t: %s\n", 
-					selected_step->job);
+			while((selected_step = list_next(itr))) {
+				if(selected_step->step) 
+					fprintf(stderr, "\t: %s.%s\n",
+						selected_step->job,
+						selected_step->step);
+				else	
+					fprintf(stderr, "\t: %s\n", 
+						selected_step->job);
+			}
 			list_iterator_destroy(itr);
 		}
 	}
@@ -1008,6 +982,7 @@ void do_dump(void)
 	ListIterator itr_step = NULL;
 	job_rec_t *job = NULL;
 	step_rec_t *step = NULL;
+	float tempf;
 
 	itr = list_iterator_create(jobs);
 	while((job = list_next(itr))) {
@@ -1026,8 +1001,20 @@ void do_dump(void)
 				continue;
 		if(job->sacct.min_cpu == NO_VAL)
 			job->sacct.min_cpu = 0;
+
+		if(list_count(job->steps)) {
+			tempf = job->sacct.ave_cpu/list_count(job->steps);
+			job->sacct.ave_cpu = (uint32_t)tempf;
+			tempf = job->sacct.ave_rss/list_count(job->steps);
+			job->sacct.ave_rss = (uint32_t)tempf;
+			tempf = job->sacct.ave_vsize/list_count(job->steps);
+			job->sacct.ave_vsize = (uint32_t)tempf;
+			tempf = job->sacct.ave_pages/list_count(job->steps);
+			job->sacct.ave_pages = (uint32_t)tempf;
+		}
+
 		/* JOB_START */
-		if (params.opt_jobstep_list == NULL) {
+		if (job->show_full) {
 			if (!job->job_start_seen && job->job_step_seen) {
 				/* If we only saw JOB_TERMINATED, the
 				 * job was probably canceled. */ 
@@ -1103,7 +1090,7 @@ void do_dump(void)
 		}
 		list_iterator_destroy(itr_step);
 		/* JOB_TERMINATED */
-		if (params.opt_jobstep_list == NULL) {
+		if (job->show_full) {
 			_dump_header(job->header);
 			printf("JOB_TERMINATED %d ",
 			       job->elapsed);
@@ -1603,19 +1590,18 @@ void do_help(void)
  */
 void do_list(void)
 {
-	int	do_jobs=1,
-		do_jobsteps=1;
+	int do_jobsteps = 1;
 	int rc = 0;
 	
 	ListIterator itr = NULL;
 	ListIterator itr_step = NULL;
 	job_rec_t *job = NULL;
 	step_rec_t *step = NULL;
+	float tempf;
 
 	if (params.opt_total)
 		do_jobsteps = 0;
-	else if (params.opt_jobstep_list)
-		do_jobs = 0;
+
 	itr = list_iterator_create(jobs);
 	while((job = list_next(itr))) {
 		if (!params.opt_dup)
@@ -1660,7 +1646,19 @@ void do_list(void)
 			continue;
 		if(job->sacct.min_cpu == NO_VAL)
 			job->sacct.min_cpu = 0;
-		if (do_jobs) {
+		
+		if(list_count(job->steps)) {
+			tempf = job->sacct.ave_cpu/list_count(job->steps);
+			job->sacct.ave_cpu = (uint32_t)tempf;
+			tempf = job->sacct.ave_rss/list_count(job->steps);
+			job->sacct.ave_rss = (uint32_t)tempf;
+			tempf = job->sacct.ave_vsize/list_count(job->steps);
+			job->sacct.ave_vsize = (uint32_t)tempf;
+			tempf = job->sacct.ave_pages/list_count(job->steps);
+			job->sacct.ave_pages = (uint32_t)tempf;
+		}
+
+		if (job->show_full) {
 			if (params.opt_state_list) {
 				if(!selected_status[job->status])
 					continue;
@@ -1686,6 +1684,24 @@ void do_list(void)
 	list_iterator_destroy(itr);
 }
 
+void do_stat()
+{
+	ListIterator itr = NULL;
+	uint32_t jobid = 0;
+	uint32_t stepid = 0;
+	selected_step_t *selected_step = NULL;
+	
+	itr = list_iterator_create(selected_steps);
+	while((selected_step = list_next(itr))) {
+		jobid = atoi(selected_step->job);
+		if(selected_step->step)
+			stepid = atoi(selected_step->step);
+		else
+			stepid = 0;
+		sacct_stat(jobid, stepid);
+	}
+	list_iterator_destroy(itr);
+}
 void sacct_init()
 {
 	int i=0;
diff --git a/src/sacct/print.c b/src/sacct/print.c
index 40d4bec6ebafc013acf1a800ab7383ddb734748f..4605b349f2c9f08a144d4ccf8e9977b3fb886dc2 100644
--- a/src/sacct/print.c
+++ b/src/sacct/print.c
@@ -317,14 +317,18 @@ void print_name(type_t type, void *object)
 		printf("%-18s", "------------------");
 		break;
 	case JOB:
-		if(strlen(job->jobname)<19)
+		if(!job->jobname)
+			printf("%-18s", "unknown");			     
+		else if(strlen(job->jobname)<19)
 			printf("%-18s", job->jobname);
 		else
 			printf("%-15.15s...", job->jobname);
 			
 		break;
 	case JOBSTEP:
-		if(strlen(step->stepname)<19)
+		if(!step->stepname)
+			printf("%-18s", "unknown");			     
+		else if(strlen(step->stepname)<19)
 			printf("%-18s", step->stepname);
 		else
 			printf("%-15.15s...", step->stepname);
@@ -622,14 +626,18 @@ void print_partition(type_t type, void *object)
 		printf("%-10s", "----------");
 		break;
 	case JOB:
-		if(strlen(job->header.partition)<11)
+		if(!job->header.partition)
+			printf("%-10s", "unknown");			     
+		else if(strlen(job->header.partition)<11)
 			printf("%-10s", job->header.partition);
 		else
 			printf("%-7.7s...", job->header.partition);
 		
 		break;
 	case JOBSTEP:
-		if(strlen(step->header.partition)<11)
+		if(!step->header.partition)
+			printf("%-10s", "unknown");			     
+		else if(strlen(step->header.partition)<11)
 			printf("%-10s", step->header.partition);
 		else
 			printf("%-7.7s...", step->header.partition);
@@ -651,14 +659,18 @@ void print_blockid(type_t type, void *object)
 		printf("%-16s", "----------------");
 		break;
 	case JOB:
-		if(strlen(job->header.partition)<17)
-			printf("%-16s", job->header.partition);
+		if(!job->header.blockid)
+			printf("%-16s", "unknown");			     
+		else if(strlen(job->header.blockid)<17)
+			printf("%-16s", job->header.blockid);
 		else
-			printf("%-13.13s...", job->header.partition);
+			printf("%-13.13s...", job->header.blockid);
 		
 		break;
 	case JOBSTEP:
-		if(strlen(step->header.partition)<17)
+		if(!step->header.blockid)
+			printf("%-16s", "unknown");			     
+		else if(strlen(step->header.blockid)<17)
 			printf("%-16s", step->header.blockid);
 		else
 			printf("%-13.13s...", step->header.blockid);
diff --git a/src/sacct/process.c b/src/sacct/process.c
index 7c4eaf4ac33d3e3ec23a795c4abb70a983cf4d2c..75ca5cdcc5cbe6e7dcdf470d5ff01fad054c2b60 100644
--- a/src/sacct/process.c
+++ b/src/sacct/process.c
@@ -223,7 +223,7 @@ int _parse_line(char *f[], void **data)
 	return SLURM_SUCCESS;
 }
 
-void process_start(char *f[], int lc)
+void process_start(char *f[], int lc, int show_full)
 {
 	job_rec_t *job = NULL;
 	job_rec_t *temp = NULL;
@@ -241,13 +241,13 @@ void process_start(char *f[], int lc)
 	}
 	
 	job = temp;
-	
+	job->show_full = show_full;
 	list_append(jobs, job);
 	job->job_start_seen = 1;
 	
 }
 
-void process_step(char *f[], int lc)
+void process_step(char *f[], int lc, int show_full)
 {
 	job_rec_t *job = NULL;
 	
@@ -264,13 +264,14 @@ void process_step(char *f[], int lc)
 	}
 	if (!job) {	/* fake it for now */
 		job = _init_job_rec(temp->header);
-		if ((params.opt_verbose > 1) 
-		    && (params.opt_jobstep_list==NULL)) 
+		if (params.opt_verbose > 1) 
 			fprintf(stderr, 
 				"Note: JOB_STEP record %u.%u preceded "
 				"JOB_START record at line %d\n",
 				temp->header.jobnum, temp->stepnum, lc);
 	}
+	job->show_full = show_full;
+	
 	if ((step = _find_step_record(job, temp->stepnum))) {
 		
 		if (temp->status == JOB_RUNNING) {
@@ -358,36 +359,14 @@ got_step:
 				   step->rusage.ru_nswap);
 
 	/* get the max for all the sacct_t struct */
-	if(job->sacct.max_vsize < step->sacct.max_vsize) {
-		job->sacct.max_vsize = step->sacct.max_vsize;
-		job->sacct.max_vsize_task = step->sacct.max_vsize_task;
-	}
-	job->sacct.ave_vsize += step->sacct.ave_vsize;
-	
-	if(job->sacct.max_rss < step->sacct.max_rss) {
-		job->sacct.max_rss = step->sacct.max_rss;
-		job->sacct.max_rss_task = step->sacct.max_rss_task;
-	}
-	job->sacct.ave_rss += step->sacct.ave_rss;
-	
-	if(job->sacct.max_pages < step->sacct.max_pages) {
-		job->sacct.max_pages = step->sacct.max_pages;
-		job->sacct.max_pages_task = step->sacct.max_pages_task;
-	}
-	job->sacct.ave_pages += step->sacct.ave_pages;
+	aggregate_sacct(&job->sacct, &step->sacct);
 	
-	if((job->sacct.min_cpu > step->sacct.min_cpu) 
-	   || (job->sacct.min_cpu == NO_VAL)) {
-		job->sacct.min_cpu = step->sacct.min_cpu;
-		job->sacct.min_cpu_task = step->sacct.min_cpu_task;
-	}
-	job->sacct.ave_cpu += step->sacct.ave_cpu;
 	/* job->psize = MAX(job->psize, step->psize); */
 /* 	job->vsize = MAX(job->vsize, step->vsize); */
 	job->ncpus = MAX(job->ncpus, step->ncpus);
 }
 
-void process_suspend(char *f[], int lc)
+void process_suspend(char *f[], int lc, int show_full)
 {
 	job_rec_t *job = NULL;
 	job_rec_t *temp = NULL;
@@ -397,6 +376,7 @@ void process_suspend(char *f[], int lc)
 	if (!job)    
 		job = _init_job_rec(temp->header);
 	
+	job->show_full = show_full;
 	if (job->status == JOB_SUSPENDED) 
 		job->elapsed -= temp->elapsed;
 
@@ -405,7 +385,7 @@ void process_suspend(char *f[], int lc)
 	destroy_job(temp);
 }
 	
-void process_terminated(char *f[], int lc)
+void process_terminated(char *f[], int lc, int show_full)
 {
 	job_rec_t *job = NULL;
 	job_rec_t *temp = NULL;
@@ -450,6 +430,8 @@ void process_terminated(char *f[], int lc)
 	job->status = temp->status;
 	if(list_count(job->steps) > 1)
 		job->track_steps = 1;
+	job->show_full = show_full;
+	
 finished:
 	destroy_job(temp);
 }
@@ -466,6 +448,34 @@ void convert_num(float num, char *buf)
 	snprintf(buf, 20, "%.2f%c", num, unit[count]);
 }
 
+void aggregate_sacct(sacct_t *dest, sacct_t *from)
+{
+	if(dest->max_vsize < from->max_vsize) {
+		dest->max_vsize = from->max_vsize;
+		dest->max_vsize_task = from->max_vsize_task;
+	}
+	dest->ave_vsize += from->ave_vsize;
+	
+	if(dest->max_rss < from->max_rss) {
+		dest->max_rss = from->max_rss;
+		dest->max_rss_task = from->max_rss_task;
+	}
+	dest->ave_rss += from->ave_rss;
+	
+	if(dest->max_pages < from->max_pages) {
+		dest->max_pages = from->max_pages;
+		dest->max_pages_task = from->max_pages_task;
+	}
+	dest->ave_pages += from->ave_pages;
+	
+	if((dest->min_cpu > from->min_cpu) 
+	   || (dest->min_cpu == NO_VAL)) {
+		dest->min_cpu = from->min_cpu;
+		dest->min_cpu_task = from->min_cpu_task;
+	}
+	dest->ave_cpu += from->ave_cpu;
+}
+
 void destroy_acct_header(void *object)
 {
 	acct_header_t *header = (acct_header_t *)object;
diff --git a/src/sacct/sacct.c b/src/sacct/sacct.c
index d7b5d9763609fac357373981888289548cacd807..40ce4ac8c8e0df91525d94f1dac722a1297c0bb0 100644
--- a/src/sacct/sacct.c
+++ b/src/sacct/sacct.c
@@ -192,6 +192,7 @@ int main(int argc, char **argv)
 		EXPIRE,
 		FDUMP,
 		LIST,
+		STAT,
 		HELP,
 		USAGE
 	} op;
@@ -227,13 +228,14 @@ int main(int argc, char **argv)
 		}
 	} else if (params.opt_fdump) {
 		op = FDUMP;
+	} else if (params.opt_stat) {
+		op = STAT;
 	} else if (params.opt_expire) {
 		op = EXPIRE;
 		if (params.opt_long || params.opt_total 
 		    || params.opt_field_list || 
 		    (params.opt_gid>=0) || (params.opt_uid>=0) ||
-		    params.opt_job_list || params.opt_jobstep_list ||
-		    params.opt_state_list ) {
+		    params.opt_job_list || params.opt_state_list ) {
 			if (params.opt_verbose)
 				fprintf(stderr,
 					"Switch conflict,\n"
@@ -243,7 +245,6 @@ int main(int argc, char **argv)
 					"\topt_gid=%d\n"
 					"\topt_uid=%d\n"
 					"\topt_job_list=%s\n"
-					"\topt_jobstep_list=%s\n"
 					"\topt_state_list=%s\n",
 					params.opt_long, 
 					params.opt_total, 
@@ -251,12 +252,11 @@ int main(int argc, char **argv)
 					params.opt_gid, 
 					params.opt_uid, 
 					params.opt_job_list,
-					params.opt_jobstep_list, 
 					params.opt_state_list);
 			invalidSwitchCombo("--expire",
 					   "--brief, --long, --fields, "
 					   "--total, --gid, --uid, --jobs, "
-					   "--jobstep, --state");
+					   "--state");
 			rc = 1;
 			goto finished;
 		}
@@ -281,6 +281,11 @@ int main(int argc, char **argv)
 		get_data();
 		do_list();
 		break;
+	case STAT:
+		if (params.opt_header) 	/* give them something to look */
+			_print_header();/* at while we think...        */
+		do_stat();
+		break;
 	case HELP:
 		do_help();
 		break;
diff --git a/src/sacct/sacct.h b/src/sacct/sacct.h
index c9616ddb0c1c9e8c9fdbb07749e4bfa24c973b8d..9ee59b0ef48b95157c437a8e2e8ff0864b56a4d9 100644
--- a/src/sacct/sacct.h
+++ b/src/sacct/sacct.h
@@ -42,11 +42,12 @@
 #include <unistd.h>
 
 #include "src/common/getopt.h"
-#include "src/common/slurm_protocol_api.h"
 #include "src/common/xmalloc.h"
 #include "src/common/xstring.h"
 #include "src/common/list.h"
 
+#include "src/sacct/sacct_stat.h"
+
 #define ERROR 2
 
 /* slurmd uses "(uint32_t) -2" to track data for batch allocations
@@ -173,27 +174,13 @@ typedef struct header {
 	uint16_t rec_type;
 } acct_header_t;
 
-typedef struct sacct_struct {
-       uint32_t max_vsize; 
-       uint16_t max_vsize_task;
-       float ave_vsize;
-       uint32_t max_rss;
-       uint16_t max_rss_task;
-       float ave_rss;
-       uint32_t max_pages;
-       uint16_t max_pages_task;
-       float ave_pages;
-       float min_cpu;
-       uint16_t min_cpu_task;
-       float ave_cpu;	
-} sacct_t;
-
 typedef struct job_rec {
 	uint32_t	job_start_seen,		/* useful flags */
 		job_step_seen,
 		job_terminated_seen,
 		jobnum_superseded;	/* older jobnum was reused */
 	acct_header_t header;
+	uint16_t show_full;
 	char	*nodes;
 	char	*jobname;
 	uint16_t track_steps;
@@ -241,6 +228,7 @@ typedef struct sacct_parameters {
 	int opt_dump;		/* --dump */
 	int opt_dup;		/* --duplicates; +1 = explicitly set */
 	int opt_fdump;		/* --formattted_dump */
+	int opt_stat;		/* --stat */
 	int opt_gid;		/* --gid (-1=wildcard, 0=root) */
 	int opt_header;		/* can only be cleared */
 	int opt_help;		/* --help */
@@ -255,7 +243,6 @@ typedef struct sacct_parameters {
 	char *opt_field_list;	/* --fields= */
 	char *opt_filein;	/* --file */
 	char *opt_job_list;	/* --jobs */
-	char *opt_jobstep_list;	/* --jobstep */
 	char *opt_partition_list;/* --partitions */
 	char *opt_state_list;	/* --states */
 } sacct_parameters_t;
@@ -271,11 +258,12 @@ extern int printfields[MAX_PRINTFIELDS],	/* Indexed into fields[] */
 	nprintfields;
 
 /* process.c */
-void process_start(char *f[], int lc);
-void process_step(char *f[], int lc);
-void process_suspend(char *f[], int lc);
-void process_terminated(char *f[], int lc);
+void process_start(char *f[], int lc, int show_full);
+void process_step(char *f[], int lc, int show_full);
+void process_suspend(char *f[], int lc, int show_full);
+void process_terminated(char *f[], int lc, int show_full);
 void convert_num(float num, char *buf);
+void aggregate_sacct(sacct_t *dest, sacct_t *from);
 void destroy_acct_header(void *object);
 void destroy_job(void *object);
 void destroy_step(void *object);
@@ -329,6 +317,7 @@ void do_expire(void);
 void do_fdump(char* fields[], int lc);
 void do_help(void);
 void do_list(void);
+void do_stat(void);
 void sacct_init();
 void sacct_fini();
 
diff --git a/src/slurmctld/agent.c b/src/slurmctld/agent.c
index 9b3934be81213a87a7cdb340107eb1ee5cb8c0b4..5688dda75c2cc347f2169b62b918fbcdb2ac7ce0 100644
--- a/src/slurmctld/agent.c
+++ b/src/slurmctld/agent.c
@@ -707,7 +707,7 @@ static inline void _comm_err(char *node_name)
  */
 static void *_thread_per_group_rpc(void *args)
 {
-	int rc = SLURM_SUCCESS, timeout = SLURM_MESSAGE_TIMEOUT_MSEC_STATIC;
+	int rc = SLURM_SUCCESS;
 	slurm_msg_t msg;
 	task_info_t *task_ptr = (task_info_t *) args;
 	/* we cache some pointers from task_info_t because we need 
@@ -802,7 +802,8 @@ static void *_thread_per_group_rpc(void *args)
 	//info("forwarding to %d",msg.forward.cnt);
 	thread_ptr->end_time = thread_ptr->start_time + COMMAND_TIMEOUT;
 	if (task_ptr->get_reply) {
-		if ((ret_list = slurm_send_recv_rc_msg(&msg, timeout)) 
+		if ((ret_list = slurm_send_recv_rc_msg(&msg, 
+						       msg.forward.timeout)) 
 		    == NULL) {
 			if (!srun_agent)
 				_comm_err(thread_ptr->node_name);
diff --git a/src/slurmctld/proc_req.c b/src/slurmctld/proc_req.c
index 24b012db1d3071e4f8db7b3a0fdbeed914734ac5..6aafb07a519a7dc9b5d4a32ce18b60d09fa22780 100644
--- a/src/slurmctld/proc_req.c
+++ b/src/slurmctld/proc_req.c
@@ -99,6 +99,7 @@ inline static void  _slurm_rpc_shutdown_controller(slurm_msg_t * msg);
 inline static void  _slurm_rpc_shutdown_controller_immediate(slurm_msg_t *
 							     msg);
 inline static void  _slurm_rpc_step_complete(slurm_msg_t * msg);
+inline static void  _slurm_rpc_stat_jobacct(slurm_msg_t * msg);
 inline static void  _slurm_rpc_submit_batch_job(slurm_msg_t * msg);
 inline static void  _slurm_rpc_suspend(slurm_msg_t * msg);
 inline static void  _slurm_rpc_update_job(slurm_msg_t * msg);
@@ -276,6 +277,10 @@ void slurmctld_req (slurm_msg_t * msg)
 		_slurm_rpc_step_complete(msg);
 		slurm_free_step_complete_msg(msg->data);
 		break;
+	case MESSAGE_STAT_JOBACCT:
+		_slurm_rpc_stat_jobacct(msg);
+		slurm_free_stat_jobacct_msg(msg->data);
+		break;
 	default:
 		error("invalid RPC msg_type=%d", msg->msg_type);
 		slurm_send_rc_msg(msg, EINVAL);
@@ -574,8 +579,8 @@ static void _slurm_rpc_dump_jobs(slurm_msg_t * msg)
 		slurm_send_rc_msg(msg, SLURM_NO_CHANGE_IN_DATA);
 	} else {
 		pack_all_jobs(&dump, &dump_size, 
-				job_info_request_msg->show_flags, 
-				g_slurm_auth_get_uid(msg->cred));
+			      job_info_request_msg->show_flags, 
+			      g_slurm_auth_get_uid(msg->cred));
 		unlock_slurmctld(job_read_lock);
 		END_TIMER;
 		debug2("_slurm_rpc_dump_jobs, size=%d %s",
@@ -1528,6 +1533,85 @@ static void _slurm_rpc_step_complete(slurm_msg_t *msg)
 		(void) schedule_node_save();	/* Has own locking */
 }
 
+/* _slurm_rpc_step_complete - process step completion RPC to note the 
+ *      completion of a job step on at least some nodes.
+ *	If the job step is complete, it may 
+ *	represent the termination of an entire job */
+static void  _slurm_rpc_stat_jobacct(slurm_msg_t * msg)
+{
+	int error_code = SLURM_SUCCESS, i=0;
+	slurm_msg_t response_msg;
+	DEF_TIMERS;
+	stat_jobacct_msg_t *req = (stat_jobacct_msg_t *)msg->data;
+	resource_allocation_response_msg_t resp;
+	/* Locks: Write job, write node */
+	slurmctld_lock_t job_read_lock = { 
+		NO_LOCK, READ_LOCK, READ_LOCK, NO_LOCK };
+	uid_t uid = g_slurm_auth_get_uid(msg->cred);
+	struct job_record *job_ptr = NULL;
+	struct step_record *step_ptr = NULL;
+	char bitstring[BUFFER_SIZE];
+	int *node_pos = NULL;
+	int node_cnt = 0;
+
+	
+	START_TIMER;
+	debug2("Processing RPC: MESSAGE_STAT_JOBACCT");
+
+	lock_slurmctld(job_read_lock);
+	error_code = old_job_info(uid, req->job_id, &job_ptr);
+	END_TIMER;
+	/* return result */
+	if (error_code || (job_ptr == NULL)) {
+		unlock_slurmctld(job_read_lock);
+		debug2("_slurm_rpc_stat_jobacct: JobId=%u, uid=%u: %s",
+			req->job_id, uid, 
+			slurm_strerror(error_code));
+		slurm_send_rc_msg(msg, error_code);
+		return;
+	} else {
+		step_ptr = find_step_record(job_ptr, req->step_id);
+		if(!step_ptr) {
+			unlock_slurmctld(job_read_lock);
+			debug2("_slurm_rpc_stat_jobacct: "
+			       "JobId=%u.%u Not Found",
+			       req->job_id, req->step_id); 
+			slurm_send_rc_msg(msg, ESLURM_INVALID_JOB_ID);
+			return;
+		}
+		node_cnt = bit_set_count(step_ptr->step_node_bitmap);
+		resp.node_addr = xmalloc(sizeof(slurm_addr) * node_cnt);
+
+		bit_fmt(bitstring, BUFFER_SIZE, step_ptr->step_node_bitmap);
+		node_pos = bitfmt2int(bitstring);
+
+		for(i=0; i < node_cnt; i++) {
+			if(node_pos[i] == -1) {
+				error("error with bitfmt2int");
+				break;
+			}
+			memcpy(&resp.node_addr[i], 
+			       &job_ptr->node_addr[node_pos[i]], 
+			       sizeof(slurm_addr));			
+		}
+		resp.node_list = xstrdup(step_ptr->step_node_list);
+		resp.node_cnt = node_cnt;
+		resp.job_id = req->job_id;
+		resp.num_cpu_groups = 0;
+		resp.select_jobinfo = NULL;
+		unlock_slurmctld(job_read_lock);
+		response_msg.msg_type    = RESPONSE_RESOURCE_ALLOCATION;
+		response_msg.data        = &resp;
+		forward_init(&response_msg.forward, NULL);
+		response_msg.ret_list = NULL;
+
+		slurm_send_node_msg(msg->conn_fd, &response_msg);
+		xfree(resp.node_list);
+		xfree(resp.node_addr);	
+		xfree(node_pos);
+	}
+}
+
 /* _slurm_rpc_submit_batch_job - process RPC to submit a batch job */
 static void _slurm_rpc_submit_batch_job(slurm_msg_t * msg)
 {
diff --git a/src/slurmctld/step_mgr.c b/src/slurmctld/step_mgr.c
index b4cdd52c599b363d122473e09c00fd79532174fd..150ec5e378a8489fea6d29933167e65f8428a9c5 100644
--- a/src/slurmctld/step_mgr.c
+++ b/src/slurmctld/step_mgr.c
@@ -461,7 +461,8 @@ try_again:
 		if ((nodes_picked == NULL) || (nodes_idle == NULL))
 			fatal("bit_alloc malloc failure");
 		step_iterator = list_iterator_create (job_ptr->step_list);
-		while ((step_p = (struct step_record *) list_next (step_iterator)))
+		while ((step_p = (struct step_record *)
+			list_next(step_iterator)))
 			bit_or (nodes_idle, step_p->step_node_bitmap); 
 		list_iterator_destroy (step_iterator);
 		bit_not(nodes_idle);
diff --git a/src/slurmd/common/stepd_api.c b/src/slurmd/common/stepd_api.c
index b351c859c0384f1580518a810934a7512ac8908b..bc03f238a58497a2032f5d4f464a2232b17f379e 100644
--- a/src/slurmd/common/stepd_api.c
+++ b/src/slurmd/common/stepd_api.c
@@ -615,3 +615,33 @@ rwfail:
 	return -1;
 }
 
+/*
+ *
+ * Returns jobacctinfo_t struct on success, NULL if error.  
+ * jobacctinfo_t must be freed after calling this function.
+ */
+int 
+stepd_stat_jobacct(int fd, stat_jobacct_msg_t *sent, stat_jobacct_msg_t *resp)
+{
+	int req = MESSAGE_STAT_JOBACCT;
+	int rc = SLURM_SUCCESS;
+	//jobacctinfo_t *jobacct = NULL;
+	int tasks = 0;
+	debug("Entering stepd_stat_jobacct for job %u.%u", 
+	      sent->job_id, sent->step_id);
+	safe_write(fd, &req, sizeof(int));
+	
+	/* Receive the jobacct struct and return */
+	resp->jobacct = jobacct_g_alloc((uint16_t)NO_VAL);
+	
+	rc = jobacct_g_getinfo(resp->jobacct, JOBACCT_DATA_PIPE, &fd);	
+	safe_read(fd, &tasks, sizeof(int));
+	resp->num_tasks = tasks;
+	return rc;
+rwfail:
+	error("an error occured %d", rc);
+	jobacct_g_free(resp->jobacct);
+	resp->jobacct = NULL;
+	return rc;
+}
+
diff --git a/src/slurmd/common/stepd_api.h b/src/slurmd/common/stepd_api.h
index 7523e3564008e87741ceb3da3ca49aaaac82913f..af5480f4c9c06d92af9fa34232b2e1087405e05e 100644
--- a/src/slurmd/common/stepd_api.h
+++ b/src/slurmd/common/stepd_api.h
@@ -177,4 +177,12 @@ int stepd_resume(int fd);
  */
 int stepd_completion(int fd, step_complete_msg_t *sent);
 
+/*
+ *
+ * Returns SLURM_SUCCESS on success or SLURM_ERROR on error.  
+ * resp recieves a jobacctinfo_t which must be freed if SUCCESS.
+ */
+int stepd_stat_jobacct(int fd, stat_jobacct_msg_t *sent, 
+		       stat_jobacct_msg_t *resp);
+
 #endif /* _STEPD_API_H */
diff --git a/src/slurmd/slurmd/req.c b/src/slurmd/slurmd/req.c
index 6059d1f3ab469fdf24c7a04dc3c9d3fbd00ad02e..0c234bc6960518f9e8c08d8db39637f75d99728d 100644
--- a/src/slurmd/slurmd/req.c
+++ b/src/slurmd/slurmd/req.c
@@ -50,6 +50,7 @@
 #include "src/common/node_select.h"
 #include "src/common/slurm_auth.h"
 #include "src/common/slurm_cred.h"
+#include "src/common/slurm_jobacct.h"
 #include "src/common/slurm_protocol_defs.h"
 #include "src/common/slurm_protocol_api.h"
 #include "src/common/slurm_protocol_interface.h"
@@ -102,6 +103,7 @@ static void _rpc_pid2jid(slurm_msg_t *msg, slurm_addr *);
 static int  _rpc_file_bcast(slurm_msg_t *msg, slurm_addr *);
 static int  _rpc_ping(slurm_msg_t *, slurm_addr *);
 static int  _rpc_step_complete(slurm_msg_t *msg, slurm_addr *cli_addr);
+static int  _rpc_stat_jobacct(slurm_msg_t *msg, slurm_addr *cli_addr);
 static int  _run_prolog(uint32_t jobid, uid_t uid, char *bg_part_id);
 static int  _run_epilog(uint32_t jobid, uid_t uid, char *bg_part_id);
 
@@ -219,6 +221,10 @@ slurmd_req(slurm_msg_t *msg, slurm_addr *cli)
 		rc = _rpc_step_complete(msg, cli);
 		slurm_free_step_complete_msg(msg->data);
 		break;
+	case MESSAGE_STAT_JOBACCT:
+		rc = _rpc_stat_jobacct(msg, cli);
+		slurm_free_stat_jobacct_msg(msg->data);
+		break;
 	default:
 		error("slurmd_req: invalid request msg type %d\n",
 		      msg->msg_type);
@@ -1128,6 +1134,68 @@ done:
 	slurm_send_rc_msg(msg, rc);
 }
 
+static int
+_rpc_stat_jobacct(slurm_msg_t *msg, slurm_addr *cli_addr)
+{
+	stat_jobacct_msg_t *req = (stat_jobacct_msg_t *)msg->data;
+	slurm_msg_t        resp_msg;
+	stat_jobacct_msg_t *resp = NULL;
+	int fd;
+	uid_t req_uid;
+	uid_t job_uid;
+	
+	debug3("Entering _rpc_stat_jobacct");
+	/* step completion messages are only allowed from other slurmstepd,
+	   so only root or SlurmUser is allowed here */
+	req_uid = g_slurm_auth_get_uid(msg->cred);
+	
+	job_uid = _get_job_uid(req->job_id);
+	/* 
+	 * check that requesting user ID is the SLURM UID or root
+	 */
+	if ((req_uid != job_uid) && (!_slurm_authorized_user(req_uid))) {
+		error("stat_jobacct from uid %ld for job %u "
+		      "owned by uid %ld",
+		      (long) req_uid, req->job_id, 
+		      (long) job_uid);       
+		
+		if (msg->conn_fd >= 0) {
+			slurm_send_rc_msg(msg, ESLURM_USER_ID_MISSING);
+			return ESLURM_USER_ID_MISSING;/* or bad in this case */
+		}
+	} 
+	resp = xmalloc(sizeof(stat_jobacct_msg_t));
+	resp->job_id = req->job_id;
+	resp->step_id = req->step_id;
+	
+	fd = stepd_connect(conf->spooldir, conf->node_name,
+			   req->job_id, req->step_id);
+	if (fd == -1) {
+		error("stepd_connect to %u.%u failed: %m", 
+		      req->job_id, req->step_id);
+		slurm_send_rc_msg(msg, ESLURM_INVALID_JOB_ID);
+		slurm_free_stat_jobacct_msg(resp);
+		return	ESLURM_INVALID_JOB_ID;
+		
+	}
+	if (stepd_stat_jobacct(fd, req, resp) == SLURM_ERROR) {
+		debug("kill for nonexistent job %u.%u requested",
+		      req->job_id, req->step_id);
+	} 
+	close(fd);
+	debug("job %u.%u found", resp->job_id, resp->step_id);
+	resp_msg.address      = msg->address;
+	resp_msg.msg_type     = MESSAGE_STAT_JOBACCT;
+	resp_msg.data         = resp;
+	resp_msg.forward = msg->forward;
+	resp_msg.ret_list = msg->ret_list;
+	
+	slurm_send_node_msg(msg->conn_fd, &resp_msg);
+	slurm_free_stat_jobacct_msg(resp);
+	return SLURM_SUCCESS;
+}
+
+
 /* 
  *  For the specified job_id: reply to slurmctld, 
  *   sleep(configured kill_wait), then send SIGKILL 
@@ -1685,7 +1753,7 @@ _rpc_signal_job(slurm_msg_t *msg, slurm_addr *cli)
 	uid_t job_uid;
 	List steps;
 	ListIterator i;
-	step_loc_t *stepd;
+	step_loc_t *stepd = NULL;
 	int step_cnt  = 0;  
 	int fd;
 
diff --git a/src/slurmd/slurmstepd/req.c b/src/slurmd/slurmstepd/req.c
index 96f8035057559e72e716ca425c7ba99e697146fd..2d40aced47252f3563aacfff2278d923b045557b 100644
--- a/src/slurmd/slurmstepd/req.c
+++ b/src/slurmd/slurmstepd/req.c
@@ -67,6 +67,7 @@ static int _handle_suspend(int fd, slurmd_job_t *job, uid_t uid);
 static int _handle_resume(int fd, slurmd_job_t *job, uid_t uid);
 static int _handle_terminate(int fd, slurmd_job_t *job, uid_t uid);
 static int _handle_completion(int fd, slurmd_job_t *job, uid_t uid);
+static int _handle_stat_jobacct(int fd, slurmd_job_t *job, uid_t uid);
 static bool _msg_socket_readable(eio_obj_t *obj);
 static int _msg_socket_accept(eio_obj_t *obj, List objs);
 
@@ -465,6 +466,10 @@ _handle_request(int fd, slurmd_job_t *job, uid_t uid, gid_t gid)
 		debug("Handling REQUEST_STEP_COMPLETION");
 		rc = _handle_completion(fd, job, uid);
 		break;
+	case MESSAGE_STAT_JOBACCT:
+		debug("Handling MESSAGE_STAT_JOBACCT");
+		rc = _handle_stat_jobacct(fd, job, uid);
+		break;
 	default:
 		error("Unrecognized request: %d", req);
 		rc = SLURM_FAILURE;
@@ -504,7 +509,7 @@ _handle_signal_process_group(int fd, slurmd_job_t *job, uid_t uid)
 	int rc = SLURM_SUCCESS;
 	int signal;
 
-	debug("_handle_signal_process_group for job %u.%u",
+	debug3("_handle_signal_process_group for job %u.%u",
 	      job->jobid, job->stepid);
 
 	safe_read(fd, &signal, sizeof(int));
@@ -939,6 +944,7 @@ _handle_resume(int fd, slurmd_job_t *job, uid_t uid)
 		goto done;
 	}
 
+	jobacct_g_suspendpoll();
 	/*
 	 * Signal the container
 	 */
@@ -1025,3 +1031,42 @@ _handle_completion(int fd, slurmd_job_t *job, uid_t uid)
 rwfail:
 	return SLURM_FAILURE;
 }
+
+static int
+_handle_stat_jobacct(int fd, slurmd_job_t *job, uid_t uid)
+{
+	jobacctinfo_t *jobacct = NULL;
+	jobacctinfo_t *temp_jobacct = NULL;
+	int i = 0;
+	int num_tasks = 0;
+	debug("_handle_stat_jobacct for job %u.%u",
+	      job->jobid, job->stepid);
+
+	debug3("  uid = %d", uid);
+	if (uid != job->uid && !_slurm_authorized_user(uid)) {
+		debug("stat jobacct from uid %ld for job %u.%u "
+		      "owned by uid %ld",
+		      (long)uid, job->jobid, job->stepid, (long)job->uid);
+		/* Send NULL */
+		jobacct_g_setinfo(jobacct, JOBACCT_DATA_PIPE, &fd);	
+		return SLURM_ERROR;
+	}
+	
+	jobacct = jobacct_g_alloc((uint16_t)NO_VAL);
+	debug3("num tasks = %d", job->ntasks);
+	
+	for (i = 0; i < job->ntasks; i++) {
+		temp_jobacct = jobacct_g_stat_task(job->task[i]->pid);
+		if(temp_jobacct) {
+			jobacct_g_aggregate(jobacct, temp_jobacct);
+			num_tasks++;
+		}
+	}
+	debug3("got %d");
+	jobacct_g_setinfo(jobacct, JOBACCT_DATA_PIPE, &fd);
+	safe_write(fd, &num_tasks, sizeof(int));
+	jobacct_g_free(jobacct);
+	return SLURM_SUCCESS;
+rwfail:
+	return SLURM_ERROR;
+}