diff --git a/configure.ac b/configure.ac
index 68a544c9bf89bc0d83c16773e383d189b1a4cf00..f88e2f4eb1080f5a5c74a9797f7489391dcaa3b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -311,6 +311,7 @@ AC_CONFIG_FILES([Makefile
 		 src/sinfo/Makefile
 		 src/plugins/Makefile
 		 src/plugins/auth/Makefile
+		 src/plugins/jobcomp/Makefile
 		 doc/Makefile
 		 doc/man/Makefile
 		 testsuite/Makefile
diff --git a/src/plugins/jobcomp/Makefile.am b/src/plugins/jobcomp/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..852e7b5dc5bae5007584cf95cbaf7876c912f69c
--- /dev/null
+++ b/src/plugins/jobcomp/Makefile.am
@@ -0,0 +1,18 @@
+# $Id$
+# Makefile for jobcomp plugins
+
+AUTOMAKE_OPTIONS = foreign
+
+PLUGIN_FLAGS = -module -avoid-version --export-dynamic 
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common
+
+pkglib_LTLIBRARIES = jobcomp_none.la jobcomp_filetxt.la
+
+# Null job completion logging plugin.
+jobcomp_none_la_SOURCES = jobcomp_none.c
+jobcomp_none_la_LDFLAGS = $(PLUGIN_FLAGS)
+
+# Text file job completion logging plugin.
+jobcomp_filetxt_la_SOURCES = jobcomp_filetxt.c
+jobcomp_filetxt_la_LDFLAGS = $(PLUGIN_FLAGS)
diff --git a/src/plugins/jobcomp/jobcomp_filetxt.c b/src/plugins/jobcomp/jobcomp_filetxt.c
new file mode 100644
index 0000000000000000000000000000000000000000..609a095906fd90ddc28e1d1a1a046bc1503f63f0
--- /dev/null
+++ b/src/plugins/jobcomp/jobcomp_filetxt.c
@@ -0,0 +1,231 @@
+/*****************************************************************************\
+ *  jobcomp_filetxt.c - text file slurm job completion logging plugin.
+ *****************************************************************************
+ *  Copyright (C) 2003 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Moe Jette <jette1@llnl.gov> et. al.
+ *  UCRL-CODE-2002-040.
+ *  
+ *  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.
+ *  
+ *  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.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+\*****************************************************************************/
+
+#if HAVE_CONFIG_H
+#   include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <slurm/slurm.h>
+#include <slurm/slurm_errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "src/common/macros.h"
+#include "src/common/slurm_jobcomp.h"
+#include "src/common/xmalloc.h"
+#include "src/common/xstring.h"
+
+#define JOB_FORMAT "JobId=%lu UserId=%s(%lu) Name=%s JobState=%s Partition=%s"\
+		" TimeLimit=%s StartTime=%s EndTime=%s NodeList=%s\n"
+
+/*
+ * These variables are required by the generic plugin interface.  If they
+ * are not found in the plugin, the plugin loader will ignore it.
+ *
+ * plugin_name - a string giving a human-readable description of the
+ * plugin.  There is no maximum length, but the symbol must refer to
+ * a valid string.
+ *
+ * plugin_type - a string suggesting the type of the plugin or its
+ * applicability to a particular form of data or method of data handling.
+ * If the low-level plugin API is used, the contents of this string are
+ * unimportant and may be anything.  SLURM uses the higher-level plugin
+ * interface which requires this string to be of the form
+ *
+ *	<application>/<method>
+ *
+ * where <application> is a description of the intended application of
+ * the plugin (e.g., "jobcomp" for SLURM job completion logging) and <method>
+ * is a description of how this plugin satisfies that application.  SLURM will
+ * only load job completion logging plugins if the plugin_type string has a 
+ * prefix of "jobcomp/".
+ *
+ * plugin_version - an unsigned 32-bit integer giving the version number
+ * of the plugin.  If major and minor revisions are desired, the major
+ * version number may be multiplied by a suitable magnitude constant such
+ * as 100 or 1000.  Various SLURM versions will likely require a certain
+ * minimum versions for their plugins as the job completion logging API 
+ * matures.
+ */
+const char plugin_name[]       	= "Job completion text file logging plugin";
+const char plugin_type[]       	= "jobcomp/filetxt";
+const uint32_t plugin_version	= 90;
+
+/* A plugin-global errno. */
+static int plugin_errno = SLURM_SUCCESS;
+
+/* File descriptor used for logging */
+static pthread_mutex_t  file_lock = PTHREAD_MUTEX_INITIALIZER;
+static char *           log_name  = NULL;
+
+/*
+ * init() is called when the plugin is loaded, before any other functions
+ * are called.  Put global initialization here.
+ */
+int init ( void )
+{
+	return SLURM_SUCCESS;
+}
+
+/*
+ * The remainder of this file implements the standard SLURM job completion
+ * logging API.
+ */
+
+int slurm_jobcomp_set_location ( char * location )
+{
+	int rc = SLURM_SUCCESS;
+	int job_comp_fd = -1;
+
+	if (location == NULL) {
+		plugin_errno = EACCES;
+		return SLURM_ERROR;
+	}
+
+	slurm_mutex_lock( &file_lock );
+	job_comp_fd = open(location, O_WRONLY | O_CREAT | O_APPEND, 0644);
+	if (job_comp_fd == -1) {
+		error("open %s: %m", location);
+		plugin_errno = errno;
+		rc = SLURM_ERROR;
+	} else {
+		fchmod(job_comp_fd, 0644);
+		close(job_comp_fd);
+		xfree(log_name);
+		log_name = xstrdup(location);
+	}
+	slurm_mutex_unlock( &file_lock );
+	return rc;
+}
+
+/* get the user name for the give user_id */
+static void
+_get_user_name(uint32_t user_id, char *user_name, int buf_size)
+{
+	static uint32_t cache_uid      = 0;
+	static char     cache_name[32] = "root";
+	struct passwd * user_info      = NULL;
+
+	if (user_id == cache_uid)
+		snprintf(user_name, buf_size, cache_name);
+	else {
+		user_info = getpwuid((uid_t) user_id);
+		if (user_info && user_info->pw_name[0])
+			snprintf(user_name, buf_size, "%s",user_info->pw_name);
+		else
+			snprintf(user_name, buf_size, "Unknown");
+		cache_uid = user_id;
+		snprintf(cache_name, sizeof(cache_name), user_info->pw_name);
+	}
+}
+
+/*
+ * make_time_str - convert time_t to string with "month/date hour:min:sec" 
+ * IN time     - a time stamp
+ * IN str_size - size of string buffer
+ * OUT string  - pointer user defined buffer
+ */
+static void
+_make_time_str (time_t *time, char *string, int str_size)
+{
+	struct tm time_tm;
+
+	localtime_r (time, &time_tm);
+	snprintf ( string, str_size, "%2.2u/%2.2u-%2.2u:%2.2u:%2.2u",
+		(time_tm.tm_mon+1), time_tm.tm_mday,
+		time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec);
+}
+
+int slurm_jobcomp_log_record ( uint32_t job_id, uint32_t user_id, 
+		char *job_name, char *job_state, char *partition, 
+		uint32_t time_limit, time_t start_time, 
+		time_t end_time, char *node_list)
+{
+	int rc = SLURM_SUCCESS;
+	int job_comp_fd = -1;
+
+	slurm_mutex_lock( &file_lock );
+	job_comp_fd = open(log_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
+	if (job_comp_fd == -1) {
+		error("open %s: %m", log_name);
+		plugin_errno = errno;
+		rc = SLURM_ERROR;
+	} else {
+		char job_rec[256];
+		char usr_str[32], start_str[32], end_str[32], lim_str[32];
+		size_t offset = 0, tot_size, wrote;
+
+		fchmod(job_comp_fd, 0644);
+		_get_user_name(user_id, usr_str, sizeof(usr_str));
+		if (time_limit == INFINITE)
+			strcpy(lim_str, "UNLIMITED");
+		else
+			snprintf(lim_str, sizeof(lim_str), "%lu", 
+					(unsigned long) time_limit);
+		_make_time_str(&start_time, start_str, sizeof(start_str));
+		_make_time_str(&end_time,   end_str,   sizeof(end_str));
+		snprintf(job_rec, sizeof(job_rec), JOB_FORMAT,
+				(unsigned long) job_id, usr_str, 
+				(unsigned long) user_id, job_name, 
+				job_state, partition, lim_str, start_str, 
+				end_str, node_list);
+		tot_size = (strlen(job_rec) + 1);
+
+		while ( offset < tot_size ) {
+			wrote = write(job_comp_fd, job_rec + offset,
+				tot_size - offset);
+			if (wrote == -1) {
+				if (errno == EAGAIN)
+					continue;
+				else {
+					plugin_errno = errno;
+					rc = SLURM_ERROR;
+					break;
+				}
+			}
+			offset += wrote;
+		}
+		close(job_comp_fd);
+	}
+	slurm_mutex_unlock( &file_lock );
+	return rc;
+}
+
+int slurm_jobcomp_get_errno( void )
+{
+	return plugin_errno;
+}
+
+int fini ( void )
+{
+	return SLURM_SUCCESS;
+}
diff --git a/src/plugins/jobcomp/jobcomp_none.c b/src/plugins/jobcomp/jobcomp_none.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c5c6353c992caf4ab4a098652c01fe8dba101d0
--- /dev/null
+++ b/src/plugins/jobcomp/jobcomp_none.c
@@ -0,0 +1,100 @@
+/*****************************************************************************\
+ *  jobcomp_none.c - NO-OP slurm job completion logging plugin.
+ *****************************************************************************
+ *  Copyright (C) 2002 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Kevin Tew <tew1@llnl.gov> et. al.
+ *  UCRL-CODE-2002-040.
+ *  
+ *  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.
+ *  
+ *  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.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+\*****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <slurm/slurm_errno.h>
+
+#include "src/common/slurm_jobcomp.h"
+
+/*
+ * These variables are required by the generic plugin interface.  If they
+ * are not found in the plugin, the plugin loader will ignore it.
+ *
+ * plugin_name - a string giving a human-readable description of the
+ * plugin.  There is no maximum length, but the symbol must refer to
+ * a valid string.
+ *
+ * plugin_type - a string suggesting the type of the plugin or its
+ * applicability to a particular form of data or method of data handling.
+ * If the low-level plugin API is used, the contents of this string are
+ * unimportant and may be anything.  SLURM uses the higher-level plugin
+ * interface which requires this string to be of the form
+ *
+ *	<application>/<method>
+ *
+ * where <application> is a description of the intended application of
+ * the plugin (e.g., "jobcomp" for SLURM job completion logging) and <method>
+ * is a description of how this plugin satisfies that application.  SLURM will
+ * only load job completion logging plugins if the plugin_type string has a 
+ * prefix of "jobcomp/".
+ *
+ * plugin_version - an unsigned 32-bit integer giving the version number
+ * of the plugin.  If major and minor revisions are desired, the major
+ * version number may be multiplied by a suitable magnitude constant such
+ * as 100 or 1000.  Various SLURM versions will likely require a certain
+ * minimum versions for their plugins as the job completion logging API 
+ * matures.
+ */
+const char plugin_name[]       	= "Job completion logging NONE plugin";
+const char plugin_type[]       	= "jobcomp/none";
+const uint32_t plugin_version	= 90;
+
+/*
+ * init() is called when the plugin is loaded, before any other functions
+ * are called.  Put global initialization here.
+ */
+int init ( void )
+{
+	return SLURM_SUCCESS;
+}
+
+/*
+ * The remainder of this file implements the standard SLURM job completion
+ * logging API.
+ */
+
+int slurm_jobcomp_set_location ( char * location )
+{
+	return SLURM_SUCCESS;
+}
+
+int slurm_jobcomp_log_record ( uint32_t job_id, uint32_t user_id, char *job_name,
+		char *job_state, char *partition, uint32_t time_limit,
+		time_t start, time_t end_time, char *node_list)
+{
+	return SLURM_SUCCESS;
+}
+
+int slurm_jobcomp_get_errno( void )
+{
+	return SLURM_SUCCESS;
+}
+
+int fini ( void )
+{
+	return SLURM_SUCCESS;
+}