diff --git a/.at.metadata b/.at.metadata
new file mode 100644
index 0000000..36647b9
--- /dev/null
+++ b/.at.metadata
@@ -0,0 +1 @@
+9873e0c38403ef58364912d0b505fd20798fd400 SOURCES/at_3.1.13.orig.tar.gz
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bb5ef33
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/at_3.1.13.orig.tar.gz
diff --git a/README.md b/README.md
deleted file mode 100644
index 0e7897f..0000000
--- a/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The master branch has no content
- 
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
- 
-If you find this file in a distro specific branch, it means that no content has been checked in yet
diff --git a/SOURCES/at-3.1.10-filter-environment.patch b/SOURCES/at-3.1.10-filter-environment.patch
new file mode 100644
index 0000000..55fc669
--- /dev/null
+++ b/SOURCES/at-3.1.10-filter-environment.patch
@@ -0,0 +1,26 @@
+diff -up at-3.1.10/at.c.filter-environment at-3.1.10/at.c
+--- at-3.1.10/at.c.filter-environment	2014-10-02 10:21:01.684890331 +0200
++++ at-3.1.10/at.c	2014-10-02 10:21:40.678770635 +0200
+@@ -388,6 +388,22 @@ writefile(time_t runtimer, char queue)
+ 	int export = 1;
+ 	char *eqp;
+ 
++        /* Only accept alphanumerics and underscore in variable names.
++         * Also require the name to not start with a digit.
++         * Some shells don't like other variable names.
++         */
++        {
++            char *p = *atenv;
++            if (isdigit(*p))
++                export = 0;
++            for (; *p != '=' && *p != '\0'; ++p) {
++                if (!isalnum(*p) && *p != '_') {
++                    export = 0;
++                    break;
++                }
++            }
++        }
++
+ 	eqp = strchr(*atenv, '=');
+ 	if (ap == NULL)
+ 	    eqp = *atenv;
diff --git a/SOURCES/at-3.1.12-fix_no_export.patch b/SOURCES/at-3.1.12-fix_no_export.patch
new file mode 100644
index 0000000..60e093a
--- /dev/null
+++ b/SOURCES/at-3.1.12-fix_no_export.patch
@@ -0,0 +1,15 @@
+diff -up at-3.1.12/at.c.noexport at-3.1.12/at.c
+--- at-3.1.12/at.c.noexport	2011-06-10 14:21:04.000000000 +0200
++++ at-3.1.12/at.c	2011-06-10 14:22:54.247712577 +0200
+@@ -391,8 +391,9 @@ writefile(time_t runtimer, char queue)
+ 	    unsigned int i;
+ 	    for (i = 0; i < sizeof(no_export) / sizeof(no_export[0]); i++) {
+ 		export = export
+-		    && (strncmp(*atenv, no_export[i],
+-				(size_t) (eqp - *atenv)) != 0);
++		    && ((((size_t) (eqp - *atenv)) != strlen(no_export[i]))
++			||(strncmp(*atenv, no_export[i],(size_t) (eqp - *atenv)) != 0)
++			);
+ 	    }
+ 	    eqp++;
+ 	}
diff --git a/SOURCES/at-3.1.12-nowrap.patch b/SOURCES/at-3.1.12-nowrap.patch
new file mode 100644
index 0000000..f18167b
--- /dev/null
+++ b/SOURCES/at-3.1.12-nowrap.patch
@@ -0,0 +1,19 @@
+diff -up at-3.1.12/at.c.nowrap at-3.1.12/at.c
+--- at-3.1.12/at.c.nowrap	2010-02-18 14:39:50.125518422 +0100
++++ at-3.1.12/at.c	2010-02-22 13:20:03.817150406 +0100
+@@ -308,10 +308,13 @@ writefile(time_t runtimer, char queue)
+ 	    if (*ap == ' ')
+ 		*ap = '0';
+ 
+-	if (stat(atfile, &statbuf) != 0)
++	/*if (stat(atfile, &statbuf) != 0) {
+ 	    if (errno != ENOENT)
+ 		perr("Cannot access " ATJOB_DIR);
+-
++	} else {
++	    perr("atjob file already exists; bailing");
++	}
++	*/
+ 	/* Create the file. The x bit is only going to be set after it has
+ 	 * been completely written out, to make sure it is not executed in the
+ 	 * meantime.  To make sure they do not get deleted, turn off their r
diff --git a/SOURCES/at-3.1.12-opt_V.patch b/SOURCES/at-3.1.12-opt_V.patch
new file mode 100644
index 0000000..d25148d
--- /dev/null
+++ b/SOURCES/at-3.1.12-opt_V.patch
@@ -0,0 +1,17 @@
+diff -up at-3.1.12/at.c.opt_V at-3.1.12/at.c
+--- at-3.1.12/at.c.opt_V	2009-11-23 16:11:52.000000000 +0100
++++ at-3.1.12/at.c	2009-12-02 13:20:29.770215516 +0100
+@@ -853,10 +853,9 @@ main(int argc, char **argv)
+      */
+ 
+     if (disp_version) {
+-	fprintf(stderr, "at version " VERSION "\n"
+-	   "Please report bugs to the Debian bug tracking system (http://bugs.debian.org/)\n"
+-	   "or contact the maintainers (at@packages.debian.org).\n");
+-	exit(EXIT_SUCCESS);
++	fprintf(stderr, "at version " VERSION "\n");
++	if (argc == 2)
++		exit(EXIT_SUCCESS);
+     }
+ 
+     /* select our program
diff --git a/SOURCES/at-3.1.12-shell.patch b/SOURCES/at-3.1.12-shell.patch
new file mode 100644
index 0000000..617b8f9
--- /dev/null
+++ b/SOURCES/at-3.1.12-shell.patch
@@ -0,0 +1,55 @@
+diff -up at-3.1.12/at.c.shell at-3.1.12/at.c
+--- at-3.1.12/at.c.shell	2009-12-02 13:25:12.706989310 +0100
++++ at-3.1.12/at.c	2009-12-02 13:26:01.991966200 +0100
+@@ -62,11 +62,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-#ifdef TM_IN_SYS_TIME
+ #include <sys/time.h>
+-#else
+ #include <time.h>
+-#endif
+ 
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+@@ -244,6 +241,12 @@ writefile(time_t runtimer, char queue)
+     int kill_errno;
+     int rc;
+     int mailsize = 128;
++    struct timeval tv;
++    struct timezone tz;
++    long int i;
++
++    gettimeofday(&tv, &tz);
++    srandom(getpid()+tv.tv_usec);
+ 
+ /* Install the signal handler for SIGINT; terminate after removing the
+  * spool file if necessary
+@@ -461,6 +464,9 @@ writefile(time_t runtimer, char queue)
+     fprintf(fp, " || {\n\t echo 'Execution directory "
+ 	    "inaccessible' >&2\n\t exit 1\n}\n");
+ 
++    i = random();
++    fprintf(fp, "${SHELL:-/bin/sh} << \'marcinDELIMITER%08lx\'\n", i);
++
+     istty = isatty(fileno(stdin));
+     if (istty) {
+ 	fprintf(stderr, "at> ");
+@@ -477,6 +483,7 @@ writefile(time_t runtimer, char queue)
+ 	fprintf(stderr, "<EOT>\n");
+     }
+     fprintf(fp, "\n");
++    fprintf(fp, "marcinDELIMITER%08lx\n", i);
+     if (ferror(fp))
+ 	panic("Output error");
+ 
+@@ -926,7 +933,7 @@ main(int argc, char **argv)
+ 	   It also alows a warning diagnostic to be printed.  Because of the
+ 	   possible variance, we always output the diagnostic. */
+ 
+-	fprintf(stderr, "warning: commands will be executed using /bin/sh\n");
++	//fprintf(stderr, "warning: commands will be executed using /bin/sh\n");
+ 
+ 	writefile(timer, queue);
+ 	break;
diff --git a/SOURCES/at-3.1.13-aborted-jobs.patch b/SOURCES/at-3.1.13-aborted-jobs.patch
new file mode 100644
index 0000000..7a85b4e
--- /dev/null
+++ b/SOURCES/at-3.1.13-aborted-jobs.patch
@@ -0,0 +1,126 @@
+diff -up at-3.1.13/atd.c.aborted at-3.1.13/atd.c
+--- at-3.1.13/atd.c.aborted	2016-04-22 13:30:58.563029540 +0200
++++ at-3.1.13/atd.c	2017-09-14 16:00:38.109011916 +0200
+@@ -74,6 +74,9 @@
+ #include <syslog.h>
+ #endif
+ 
++#include <sys/file.h>
++#include <utime.h>
++
+ /* Local headers */
+ 
+ #include "privs.h"
+@@ -285,7 +288,7 @@ run_file(const char *filename, uid_t uid
+  * mail to the user.
+  */
+     pid_t pid;
+-    int fd_out, fd_in;
++    int fd_out, fd_in, fd_std;
+     char jobbuf[9];
+     char *mailname = NULL;
+     int mailsize = 128;
+@@ -404,6 +407,10 @@ run_file(const char *filename, uid_t uid
+ 
+     fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC);
+ 
++    if (flock(fd_in, LOCK_EX | LOCK_NB) != 0)
++	    perr("Somebody already locked the job %8lu (%.500s) - "
++	     "aborting", jobno, filename);
++
+     /*
+      * If the spool directory is mounted via NFS `atd' isn't able to
+      * read from the job file and will bump out here.  The file is
+@@ -563,10 +570,7 @@ run_file(const char *filename, uid_t uid
+ 	PRIV_END
+     }
+     /* We're the parent.  Let's wait.
+-     */
+-    close(fd_in);
+-
+-    /* We inherited the master's SIGCHLD handler, which does a
++       We inherited the master's SIGCHLD handler, which does a
+        non-blocking waitpid. So this blocking one will eventually
+        return with an ECHILD error. 
+      */
+@@ -583,14 +587,14 @@ run_file(const char *filename, uid_t uid
+     /* some sendmail implementations are confused if stdout, stderr are
+      * not available, so let them point to /dev/null
+      */
+-    if ((fd_in = open("/dev/null", O_WRONLY)) < 0)
++    if ((fd_std = open("/dev/null", O_WRONLY)) < 0)
+ 	perr("Could not open /dev/null.");
+-    if (dup2(fd_in, STDOUT_FILENO) < 0)
++    if (dup2(fd_std, STDOUT_FILENO) < 0)
+ 	perr("Could not use /dev/null as standard output.");
+-    if (dup2(fd_in, STDERR_FILENO) < 0)
++    if (dup2(fd_std, STDERR_FILENO) < 0)
+ 	perr("Could not use /dev/null as standard error.");
+-    if (fd_in != STDOUT_FILENO && fd_in != STDERR_FILENO)
+-	close(fd_in);
++    if (fd_std != STDOUT_FILENO && fd_std != STDERR_FILENO)
++	close(fd_std);
+ 
+     if (unlink(filename) == -1)
+         syslog(LOG_WARNING, "Warning: removing output file for job %li failed: %s",
+@@ -598,7 +602,12 @@ run_file(const char *filename, uid_t uid
+ 
+     /* The job is now finished.  We can delete its input file.
+      */
+-    chdir(ATJOB_DIR);
++    if (chdir(ATJOB_DIR) != 0)
++	perr("Somebody removed %s directory from under us.", ATJOB_DIR);
++
++    /* This also removes the flock */
++    (void)close(fd_in);
++
+     unlink(newname);
+     free(newname);
+ 
+@@ -642,7 +651,7 @@ run_file(const char *filename, uid_t uid
+ 	PRIV_END
+    }
+    else if ( mail_pid == -1 ) {
+-           perr("fork of mailer failed");
++           syslog(LOG_ERR, "fork of mailer failed: %m");
+    }
+    else {
+            /* Parent */
+@@ -738,8 +747,16 @@ run_loop()
+ 	/* Skip lock files */
+ 	if (queue == '=') {
+ 	    if ((buf.st_nlink == 1) && (run_time + CHECK_INTERVAL <= now)) {
+-		/* Remove stale lockfile FIXME: lock the lockfile, if you fail, it's still in use. */
+-		unlink(dirent->d_name);
++		int fd;
++
++		fd = open(dirent->d_name, O_RDONLY);
++		if (fd != -1) {
++			if (flock(fd, LOCK_EX | LOCK_NB) == 0) {
++				unlink(dirent->d_name);
++				syslog(LOG_NOTICE, "removing stale lock file %s\n", dirent->d_name);
++			}
++			(void)close(fd);
++		}
+ 	    }
+ 	    continue;
+ 	}
+@@ -752,12 +769,17 @@ run_loop()
+ 	/* Is the file already locked?
+ 	 */
+ 	if (buf.st_nlink > 1) {
++	    if (run_time < buf.st_mtime)
++		run_time = buf.st_mtime;
+ 	    if (run_time + CHECK_INTERVAL <= now) {
+-
+ 		/* Something went wrong the last time this was executed.
+ 		 * Let's remove the lockfile and reschedule.
++		 * We also change the timestamp to avoid rerunning the job more
++		 * than once every CHECK_INTERVAL.
+ 		 */
+ 		strncpy(lock_name, dirent->d_name, sizeof(lock_name));
++		if (utime(lock_name, 0) < 0)
++			syslog(LOG_ERR, "utime couldn't be set for lock file %s\n", lock_name);
+ 		lock_name[sizeof(lock_name)-1] = '\0';
+ 		lock_name[0] = '=';
+ 		unlink(lock_name);
diff --git a/SOURCES/at-3.1.13-clear-nonjobs.patch b/SOURCES/at-3.1.13-clear-nonjobs.patch
new file mode 100644
index 0000000..14fd9ba
--- /dev/null
+++ b/SOURCES/at-3.1.13-clear-nonjobs.patch
@@ -0,0 +1,42 @@
+diff -up at-3.1.13/atd.c.clear-nonjobs at-3.1.13/atd.c
+--- at-3.1.13/atd.c.clear-nonjobs	2016-04-20 17:15:00.579327865 +0200
++++ at-3.1.13/atd.c	2016-04-20 17:18:06.215376744 +0200
+@@ -414,10 +414,22 @@ run_file(const char *filename, uid_t uid
+     sprintf(fmt, "#!/bin/sh\n# atrun uid=%%d gid=%%d\n# mail %%%ds %%d",
+ 	mailsize );
+ 
++    /* Unlink the file unless there was an error reading it (perhaps
++     * temporary).
++     * If the file has a bogus format there is no reason in trying
++     * to run it again and again.
++     */
+     if (fscanf(stream, fmt,
+-	       &nuid, &ngid, mailname, &send_mail) != 4)
+-	pabort("File %.500s is in wrong format - aborting",
+-	       filename);
++	       &nuid, &ngid, mailname, &send_mail) != 4) {
++		if (ferror(stream))
++			perr("Error reading the job file");
++
++		unlink(filename);
++		pabort("File %.500s is in wrong format - aborting",
++			filename);
++    }
++
++    unlink(filename);
+ 
+     if (mailname[0] == '-')
+ 	pabort("illegal mail name %.300s in job %8lu (%.300s)", mailname,
+@@ -427,12 +439,6 @@ run_file(const char *filename, uid_t uid
+ 	pabort("Job %8lu (%.500s) - userid %d does not match file uid %d",
+ 	       jobno, filename, nuid, uid);
+ 
+-    /* We are now committed to executing this script.  Unlink the
+-     * original.
+-     */
+-
+-    unlink(filename);
+-
+     fclose(stream);
+     if (chdir(ATSPOOL_DIR) < 0)
+ 	perr("Cannot chdir to " ATSPOOL_DIR);
diff --git a/SOURCES/at-3.1.13-fclose-error.patch b/SOURCES/at-3.1.13-fclose-error.patch
new file mode 100644
index 0000000..74d4958
--- /dev/null
+++ b/SOURCES/at-3.1.13-fclose-error.patch
@@ -0,0 +1,26 @@
+diff -up at-3.1.13/at.c.fclose at-3.1.13/at.c
+--- at-3.1.13/at.c.fclose	2016-04-20 17:15:00.584327893 +0200
++++ at-3.1.13/at.c	2016-04-20 17:15:50.453609665 +0200
+@@ -209,7 +209,11 @@ nextjob()
+     jobno = (1 + jobno) % 0xfffff;	/* 2^20 jobs enough? */
+     fprintf(fid, "%05lx\n", jobno);
+ 
+-    fclose(fid);
++    if (ferror(fid))
++	jobno = EOF;
++
++    if (fclose(fid) != 0)
++	jobno = EOF;
+     return jobno;
+ }
+ 
+@@ -498,7 +502,8 @@ writefile(time_t runtimer, char queue)
+     if (ferror(stdin))
+ 	panic("Input error");
+ 
+-    fclose(fp);
++    if (fclose(fp) != 0)
++	panic("Output error");
+ 
+     /* Set the x bit so that we're ready to start executing
+      */
diff --git a/SOURCES/at-3.1.13-help.patch b/SOURCES/at-3.1.13-help.patch
new file mode 100644
index 0000000..8014526
--- /dev/null
+++ b/SOURCES/at-3.1.13-help.patch
@@ -0,0 +1,15 @@
+diff -up at-3.1.13/at.c.add at-3.1.13/at.c
+diff -up at-3.1.13/panic.c.add at-3.1.13/panic.c
+--- at-3.1.13/panic.c.add	2012-01-27 13:54:46.216466452 +0100
++++ at-3.1.13/panic.c	2012-01-27 13:57:35.123747498 +0100
+@@ -92,8 +92,8 @@ usage(void)
+ {
+ /* Print usage and exit.
+  */
+-    fprintf(stderr, "Usage: at [-V] [-q x] [-f file] [-mlbv] timespec ...\n"
+-            "       at [-V] [-q x] [-f file] [-mlbv] -t time\n"
++    fprintf(stderr, "Usage: at [-V] [-q x] [-f file] [-mMlbv] timespec ...\n"
++            "       at [-V] [-q x] [-f file] [-mMlbv] -t time\n"
+     	    "       at -c job ...\n"
+ 	    "       atq [-V] [-q x]\n"
+ 	    "       at [ -rd ] job ...\n"
diff --git a/SOURCES/at-3.1.13-mailwithhostname.patch b/SOURCES/at-3.1.13-mailwithhostname.patch
new file mode 100644
index 0000000..a3e5933
--- /dev/null
+++ b/SOURCES/at-3.1.13-mailwithhostname.patch
@@ -0,0 +1,62 @@
+diff -up at-3.1.13/atd.c.hostname at-3.1.13/atd.c
+--- at-3.1.13/atd.c.hostname	2012-01-12 18:19:36.000000000 +0100
++++ at-3.1.13/atd.c	2012-01-12 18:52:34.000000000 +0100
+@@ -99,6 +99,10 @@ int selinux_enabled=0;
+ #define BATCH_INTERVAL_DEFAULT 60
+ #define CHECK_INTERVAL 3600
+ 
++#ifndef MAXHOSTNAMELEN
++#define MAXHOSTNAMELEN 64
++#endif
++
+ /* Global variables */
+ 
+ uid_t real_uid, effective_uid;
+@@ -116,6 +120,7 @@ static time_t last_chg;
+ static int nothing_to_do;
+ unsigned int batch_interval;
+ static int run_as_daemon = 0;
++static int mail_with_hostname = 0;
+ 
+ static volatile sig_atomic_t term_signal = 0;
+ 
+@@ -297,6 +302,7 @@ run_file(const char *filename, uid_t uid
+     char fmt[64];
+     unsigned long jobno;
+     int rc;
++    char hostbuf[MAXHOSTNAMELEN];
+ #ifdef WITH_PAM
+     int retcode;
+ #endif
+@@ -451,6 +457,11 @@ run_file(const char *filename, uid_t uid
+ 
+     write_string(fd_out, "Subject: Output from your job ");
+     write_string(fd_out, jobbuf);
++    if (mail_with_hostname > 0) {
++		gethostname(hostbuf, MAXHOSTNAMELEN-1);
++        write_string(fd_out, " ");
++        write_string(fd_out, hostbuf);
++    }
+     write_string(fd_out, "\nTo: ");
+     write_string(fd_out, mailname);    
+     write_string(fd_out, "\n\n");
+@@ -910,7 +921,7 @@ main(int argc, char *argv[])
+     run_as_daemon = 1;
+     batch_interval = BATCH_INTERVAL_DEFAULT;
+ 
+-    while ((c = getopt(argc, argv, "sdl:b:f")) != EOF) {
++    while ((c = getopt(argc, argv, "sdnl:b:f")) != EOF) {
+ 	switch (c) {
+ 	case 'l':
+ 	    if (sscanf(optarg, "%lf", &load_avg) != 1)
+@@ -932,6 +943,10 @@ main(int argc, char *argv[])
+ 	    daemon_foreground++;
+ 	    break;
+ 
++	case 'n':
++	    mail_with_hostname=1;
++	    break;
++
+ 	case 's':
+ 	    run_as_daemon = 0;
+ 	    break;
diff --git a/SOURCES/at-3.1.13-makefile.patch b/SOURCES/at-3.1.13-makefile.patch
new file mode 100644
index 0000000..edcdff6
--- /dev/null
+++ b/SOURCES/at-3.1.13-makefile.patch
@@ -0,0 +1,82 @@
+diff -up at-3.1.13/Makefile.in.make at-3.1.13/Makefile.in
+--- at-3.1.13/Makefile.in.make	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/Makefile.in	2011-07-29 08:06:28.317600053 +0200
+@@ -65,13 +65,13 @@ LIST = Filelist Filelist.asc
+ all: at atd atrun
+ 
+ at: $(ATOBJECTS)
+-	$(CC) $(CFLAGS) -o at $(ATOBJECTS) $(LIBS) $(LEXLIB)
++	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,now -o at -pie $(ATOBJECTS) $(LIBS) $(LEXLIB) $(SELINUXLIB) $(PAMLIB)
+ 	rm -f $(CLONES)
+ 	$(LN_S) -f at atq
+ 	$(LN_S) -f at atrm
+ 
+ atd: $(RUNOBJECTS)
+-	$(CC) $(CFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB)
++	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,now -o atd -pie $(RUNOBJECTS) $(LIBS) $(SELINUXLIB) $(PAMLIB) 
+ 
+ y.tab.c y.tab.h: parsetime.y
+ 	$(YACC) -d parsetime.y
+@@ -83,38 +83,41 @@ atrun: atrun.in
+ 	configure
+ 
+ .c.o:
+-	$(CC) -c $(CFLAGS) $(DEFS) $*.c
++	$(CC) -c $(CFLAGS) -fPIE $(DEFS) $*.c
+ 
+ install: all
+-	$(INSTALL) -g root -o root -m 755 -d $(IROOT)$(etcdir)
+-	$(INSTALL) -g root -o root -m 755 -d $(IROOT)$(bindir)
+-	$(INSTALL) -g root -o root -m 755 -d $(IROOT)$(sbindir)
+-	$(INSTALL) -g root -o root -m 755 -d $(IROOT)$(docdir)
+-	$(INSTALL) -g root -o root -m 755 -d $(IROOT)$(atdocdir)
+-	$(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR)
+-	chmod 1770 $(IROOT)$(ATSPOOL_DIR) $(IROOT)$(ATJOB_DIR)
++	$(INSTALL) -m 755 -d $(IROOT)$(etcdir)
++	$(INSTALL) -m 755 -d $(IROOT)$(bindir)
++	$(INSTALL) -m 755 -d $(IROOT)$(sbindir)
++	$(INSTALL) -m 755 -d $(IROOT)$(docdir)
++	$(INSTALL) -m 755 -d $(IROOT)$(atdocdir)
++	$(INSTALL) -m 755 -d $(IROOT)$(etcdir)/pam.d/
++	$(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 755 -d $(IROOT)$(ATSPOOL_DIR)
++	chmod 700 $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR)
++	chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(ATJOB_DIR) $(IROOT)$(ATSPOOL_DIR)
+ 	touch $(IROOT)$(LFILE)
+ 	chmod 600 $(IROOT)$(LFILE)
+ 	chown $(DAEMON_USERNAME):$(DAEMON_GROUPNAME) $(IROOT)$(LFILE)
+-	test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -o root -g $(DAEMON_GROUPNAME) -m 640 at.deny $(IROOT)$(etcdir)/
+-	$(INSTALL) -g $(DAEMON_GROUPNAME) -o $(DAEMON_USERNAME) -m 6755 at $(IROOT)$(bindir)
++	test -f $(IROOT)$(etcdir)/at.allow || test -f $(IROOT)$(etcdir)/at.deny || $(INSTALL) -m 600 at.deny $(IROOT)$(etcdir)/
++	$(INSTALL) -o $(INSTALL_ROOT_USER) -g $(DAEMON_GROUPNAME) pam_atd $(IROOT)$(etcdir)/pam.d/atd
++	$(INSTALL) -m 4755 at $(IROOT)$(bindir)
+ 	$(LN_S) -f at $(IROOT)$(bindir)/atq
+ 	$(LN_S) -f at $(IROOT)$(bindir)/atrm
+-	$(INSTALL) -g root -o root -m 755 batch $(IROOT)$(bindir)
+-	$(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man1dir)
+-	$(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man5dir)
+-	$(INSTALL) -d -o root -g root -m 755 $(IROOT)$(man8dir)
+-	$(INSTALL) -g root -o root -m 755 atd $(IROOT)$(sbindir)
+-	$(INSTALL) -g root -o root -m 755 atrun $(IROOT)$(sbindir)
+-	$(INSTALL) -g root -o root -m 644 at.1 $(IROOT)$(man1dir)/
++	$(INSTALL) -m 755 batch $(IROOT)$(bindir)
++	$(INSTALL) -d -m 755 $(IROOT)$(man1dir)
++	$(INSTALL) -d -m 755 $(IROOT)$(man5dir)
++	$(INSTALL) -d -m 755 $(IROOT)$(man8dir)
++	$(INSTALL) -m 755 atd $(IROOT)$(sbindir)
++	$(INSTALL) -m 755 atrun $(IROOT)$(sbindir)
++	$(INSTALL) -m 644 at.1 $(IROOT)$(man1dir)/
+ 	cd $(IROOT)$(man1dir) && $(LN_S) -f at.1 atq.1 && $(LN_S) -f at.1 batch.1 && $(LN_S) -f at.1 atrm.1
+-	$(INSTALL) -g root -o root -m 644 atd.8 $(IROOT)$(man8dir)/
++	$(INSTALL) -m 644 atd.8 $(IROOT)$(man8dir)/
+ 	sed "s,\$${exec_prefix},$(exec_prefix),g" <atrun.8>tmpman
+-	$(INSTALL) -g root -o root -m 644 tmpman $(IROOT)$(man8dir)/atrun.8
++	$(INSTALL) -m 644 tmpman $(IROOT)$(man8dir)/atrun.8
+ 	rm -f tmpman
+-	$(INSTALL) -g root -o root -m 644 at.allow.5 $(IROOT)$(man5dir)/
++	$(INSTALL) -m 644 at.allow.5 $(IROOT)$(man5dir)/
+ 	cd $(IROOT)$(man5dir) && $(LN_S) -f at.allow.5 at.deny.5
+-	$(INSTALL) -g root -o root -m 644 $(DOCS) $(IROOT)$(atdocdir)
++	$(INSTALL) -m 644 $(DOCS) $(IROOT)$(atdocdir)
+ 	rm -f $(IROOT)$(mandir)/cat1/at.1* $(IROOT)$(mandir)/cat1/batch.1* \
+ 		$(IROOT)$(mandir)/cat1/atq.1*
+ 	rm -f $(IROOT)$(mandir)/cat1/atd.8*
diff --git a/SOURCES/at-3.1.13-nitpicks.patch b/SOURCES/at-3.1.13-nitpicks.patch
new file mode 100644
index 0000000..3582593
--- /dev/null
+++ b/SOURCES/at-3.1.13-nitpicks.patch
@@ -0,0 +1,121 @@
+diff -up at-3.1.13/at.1.in.nit at-3.1.13/at.1.in
+--- at-3.1.13/at.1.in.nit	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/at.1.in	2011-07-28 13:04:41.398174737 +0200
+@@ -126,7 +126,7 @@ and to run a job at 1am tomorrow, you wo
+ .B at 1am tomorrow.
+ .PP
+ The definition of the time specification can be found in
+-.IR @prefix@/share/doc/at/timespec .
++.IR @prefix@/share/doc/at-@VERSION@/timespec .
+ .PP
+ For both
+ .BR at " and " batch ,
+@@ -204,7 +204,7 @@ queue for
+ .BR batch .
+ Queues with higher letters run with increased niceness.  The special
+ queue "=" is reserved for jobs which are currently running.
+-.P
++
+ If a job is submitted to a queue designated with an uppercase letter, the
+ job is treated as if it were submitted to batch at the time of the job.
+ Once the time is reached, the batch processing rules with respect to load
+@@ -248,7 +248,7 @@ is an alias for
+ .TP
+ .B \-v
+ Shows the time the job will be executed before reading the job.
+-.P
++
+ Times displayed will be in the format "Thu Feb 20 14:50:00 1997".
+ .TP
+ .B
+diff -up at-3.1.13/atd.c.nit at-3.1.13/atd.c
+--- at-3.1.13/atd.c.nit	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/atd.c	2011-07-28 13:01:31.577967025 +0200
+@@ -83,6 +83,9 @@
+ #include "getloadavg.h"
+ #endif
+ 
++#ifndef LOG_ATD
++#define LOG_ATD        LOG_DAEMON
++#endif
+ /* Macros */
+ 
+ #define BATCH_INTERVAL_DEFAULT 60
+@@ -194,6 +197,18 @@ myfork()
+ 
+ #define fork myfork
+ #endif
++#undef ATD_MAIL_PROGRAM
++#undef ATD_MAIL_NAME
++#if defined(SENDMAIL)
++#define ATD_MAIL_PROGRAM SENDMAIL
++#define ATD_MAIL_NAME    "sendmail"
++#elif  defined(MAILC)
++#define ATD_MAIL_PROGRAM MAILC
++#define ATD_MAIL_NAME    "mail"
++#elif  defined(MAILX)
++#define ATD_MAIL_PROGRAM MAILX
++#define ATD_MAIL_NAME    "mailx"
++#endif
+ 
+ static void
+ run_file(const char *filename, uid_t uid, gid_t gid)
+@@ -271,6 +286,9 @@ run_file(const char *filename, uid_t uid
+ 	free(newname);
+ 	return;
+     }
++
++    (void) setsid(); //own session for process
++
+     /* Let's see who we mail to.  Hopefully, we can read it from
+      * the command file; if not, send it to the owner, or, failing that,
+      * to root.
+@@ -433,6 +451,9 @@ run_file(const char *filename, uid_t uid
+ 	    if (setuid(uid) < 0)
+ 		perr("Cannot set user id");
+ 
++	    if (SIG_ERR == signal(SIGCHLD, SIG_DFL))
++		perr("Cannot reset signal handler to default");
++
+ 	    chdir("/");
+ 
+ 	    if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0)
+@@ -501,6 +522,9 @@ run_file(const char *filename, uid_t uid
+ 	    if (setuid(uid) < 0)
+ 		perr("Cannot set user id");
+ 
++	    if (SIG_ERR == signal(SIGCHLD, SIG_DFL))
++		perr("Cannot reset signal handler to default");
++
+ 	    chdir ("/");
+ 
+ #if defined(SENDMAIL)
+@@ -615,6 +639,7 @@ run_loop()
+ 		 * Let's remove the lockfile and reschedule.
+ 		 */
+ 		strncpy(lock_name, dirent->d_name, sizeof(lock_name));
++		lock_name[sizeof(lock_name)-1] = '\0';
+ 		lock_name[0] = '=';
+ 		unlink(lock_name);
+ 		next_job = now;
+@@ -649,6 +674,7 @@ run_loop()
+ 	    run_batch++;
+ 	    if (strcmp(batch_name, dirent->d_name) > 0) {
+ 		strncpy(batch_name, dirent->d_name, sizeof(batch_name));
++		batch_name[sizeof(batch_name)-1] = '\0';
+ 		batch_uid = buf.st_uid;
+ 		batch_gid = buf.st_gid;
+ 		batch_queue = queue;
+@@ -723,11 +749,7 @@ main(int argc, char *argv[])
+ 
+     RELINQUISH_PRIVS_ROOT(daemon_uid, daemon_gid)
+ 
+-#ifndef LOG_CRON
+-#define LOG_CRON	LOG_DAEMON
+-#endif
+-
+-    openlog("atd", LOG_PID, LOG_CRON);
++    openlog("atd", LOG_PID, LOG_ATD);
+ 
+     opterr = 0;
+     errno = 0;
diff --git a/SOURCES/at-3.1.13-pam.patch b/SOURCES/at-3.1.13-pam.patch
new file mode 100644
index 0000000..0bb3116
--- /dev/null
+++ b/SOURCES/at-3.1.13-pam.patch
@@ -0,0 +1,426 @@
+diff -up at-3.1.13/at.c.pam at-3.1.13/at.c
+--- at-3.1.13/at.c.pam	2012-04-19 16:50:57.491000001 +0200
++++ at-3.1.13/at.c	2012-04-19 16:50:57.505000001 +0200
+@@ -141,18 +141,13 @@ sigc(int signo)
+ /* If the user presses ^C, remove the spool file and exit 
+  */
+     if (fcreated) {
+-	/*
+         PRIV_START
+-
++        /*
+         We need the unprivileged uid here since the file is owned by the real
+         (not effective) uid.
+         */
+-        setregid(real_gid, effective_gid);
+-	    unlink(atfile);
+-        setregid(effective_gid, real_gid);
+-        /*
++	unlink(atfile);
+ 	PRIV_END
+-        */
+     }
+     exit(EXIT_FAILURE);
+ }
+@@ -318,26 +313,19 @@ writefile(time_t runtimer, char queue)
+ 	 * bit.  Yes, this is a kluge.
+ 	 */
+ 	cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR);
+-        seteuid(real_uid);
++       if ((seteuid(effective_uid)) < 0)
++	    perr("Error in seteuid: %s", errno);
+ 	if ((fd = open(atfile, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, S_IRUSR)) == -1)
+ 	    perr("Cannot create atjob file %.500s", atfile);
+-        seteuid(effective_uid);
+ 
+ 	if ((fd2 = dup(fd)) < 0)
+ 	    perr("Error in dup() of job file");
+ 
+-        /*
+ 	if (fchown(fd2, real_uid, real_gid) != 0)
+-	    perr("Cannot give away file");
+-        */
++	    perr("Cannot give real_uid and real_gid the file");
+ 
+     PRIV_END
+ 
+-    /* We no longer need suid root; now we just need to be able to write
+-     * to the directory, if necessary.
+-     */
+-
+-    REDUCE_PRIV(daemon_uid, daemon_gid)
+     /* We've successfully created the file; let's set the flag so it 
+      * gets removed in case of an interrupt or error.
+      */
+@@ -661,7 +649,7 @@ process_jobs(int argc, char **argv, int
+                     We need the unprivileged uid here since the file is owned by the real
+                     (not effective) uid.
+                     */
+-                    setregid(real_gid, effective_gid);
++		    PRIV_START
+ 
+ 		    if (queue == '=') {
+ 			fprintf(stderr, "Warning: deleting running job\n");
+@@ -670,8 +658,8 @@ process_jobs(int argc, char **argv, int
+ 			perr("Cannot unlink %.500s", dirent->d_name);
+ 			rc = EXIT_FAILURE;
+ 		    }
++		    PRIV_END
+ 
+-                    setregid(effective_gid, real_gid);
+ 		    done = 1;
+ 
+ 		    break;
+@@ -681,7 +669,7 @@ process_jobs(int argc, char **argv, int
+ 			FILE *fp;
+ 			int ch;
+ 
+-			setregid(real_gid, effective_gid);
++			PRIV_START
+ 			fp = fopen(dirent->d_name, "r");
+ 
+ 			if (fp) {
+@@ -694,7 +682,7 @@ process_jobs(int argc, char **argv, int
+ 			    perr("Cannot open %.500s", dirent->d_name);
+ 			    rc = EXIT_FAILURE;
+ 			}
+-			setregid(effective_gid, real_gid);
++			PRIV_END
+ 		    }
+ 		    break;
+ 
+diff -up at-3.1.13/atd.c.pam at-3.1.13/atd.c
+--- at-3.1.13/atd.c.pam	2012-04-19 16:50:57.498000001 +0200
++++ at-3.1.13/atd.c	2012-04-19 16:52:37.209000138 +0200
+@@ -111,7 +111,7 @@ static int run_as_daemon = 0;
+ 
+ static volatile sig_atomic_t term_signal = 0;
+ 
+-#ifdef HAVE_PAM
++#ifdef WITH_PAM
+ #include <security/pam_appl.h>
+ 
+ static pam_handle_t *pamh = NULL;
+@@ -120,15 +120,7 @@ static const struct pam_conv conv = {
+ 	NULL
+ };
+ 
+-#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
+-	fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
+-	syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
+-	pam_end(pamh, retcode); exit(1); \
+-    }
+-#define PAM_END { retcode = pam_close_session(pamh,0); \
+-		pam_end(pamh,retcode); }
+-
+-#endif /* HAVE_PAM */
++#endif /* WITH_PAM */
+ 
+ /* Signal handlers */
+ RETSIGTYPE 
+@@ -235,7 +227,7 @@ run_file(const char *filename, uid_t uid
+     char fmt[64];
+     unsigned long jobno;
+     int rc;
+-#ifdef HAVE_PAM
++#ifdef WITH_PAM
+     int retcode;
+ #endif
+ 
+@@ -395,17 +387,11 @@ run_file(const char *filename, uid_t uid
+     fstat(fd_out, &buf);
+     size = buf.st_size;
+ 
+-#ifdef HAVE_PAM
+-    PRIV_START
+-    retcode = pam_start("atd", pentry->pw_name, &conv, &pamh);
+-    PAM_FAIL_CHECK;
+-    retcode = pam_acct_mgmt(pamh, PAM_SILENT);
+-    PAM_FAIL_CHECK;
+-    retcode = pam_open_session(pamh, PAM_SILENT);
+-    PAM_FAIL_CHECK;
+-    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT);
+-    PAM_FAIL_CHECK;
+-    PRIV_END
++#ifdef WITH_PAM
++    AT_START_PAM;
++    AT_OPEN_PAM_SESSION;
++    closelog(); 
++    openlog("atd", LOG_PID, LOG_ATD);
+ #endif
+ 
+     close(STDIN_FILENO);
+@@ -419,7 +405,14 @@ run_file(const char *filename, uid_t uid
+     else if (pid == 0) {
+ 	char *nul = NULL;
+ 	char **nenvp = &nul;
++	char **pam_envp=0L;
+ 
++	PRIV_START
++#ifdef WITH_PAM
++	pam_envp = pam_getenvlist(pamh);
++	if ( ( pam_envp != 0L ) && (pam_envp[0] != 0L) )
++		nenvp = pam_envp;
++#endif
+ 	/* Set up things for the child; we want standard input from the
+ 	 * input file, and standard output and error sent to our output file.
+ 	 */
+@@ -438,8 +431,6 @@ run_file(const char *filename, uid_t uid
+ 	close(fd_in);
+ 	close(fd_out);
+ 
+-	PRIV_START
+-
+ 	    nice((tolower((int) queue) - 'a' + 1) * 2);
+ 
+ 	    if (initgroups(pentry->pw_name, pentry->pw_gid))
+@@ -458,7 +449,16 @@ run_file(const char *filename, uid_t uid
+ 
+ 	    if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0)
+ 		perr("Exec failed for /bin/sh");
+-
++#ifdef  WITH_PAM
++	    if ( ( nenvp != &nul ) && (pam_envp != 0L)  && (*pam_envp != 0L))
++	    {
++		for( nenvp = pam_envp; *nenvp != 0L; nenvp++)
++			free(*nenvp);
++		free( pam_envp );
++		nenvp = &nul;
++		pam_envp=0L;
++	    }
++#endif
+ 	PRIV_END
+     }
+     /* We're the parent.  Let's wait.
+@@ -471,14 +471,6 @@ run_file(const char *filename, uid_t uid
+      */
+     waitpid(pid, (int *) NULL, 0);
+ 
+-#ifdef HAVE_PAM
+-    PRIV_START
+-	pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
+-	retcode = pam_close_session(pamh, PAM_SILENT);
+-	pam_end(pamh, retcode);
+-    PRIV_END
+-#endif
+-
+     /* Send mail.  Unlink the output file after opening it, so it
+      * doesn't hang around after the run.
+      */
+@@ -509,8 +501,20 @@ run_file(const char *filename, uid_t uid
+     unlink(newname);
+     free(newname);
+ 
++#ifdef ATD_MAIL_PROGRAM
+     if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) {
++       int mail_pid = -1;
++#ifdef WITH_PAM
++       AT_START_PAM;
++       AT_OPEN_PAM_SESSION;
++       closelog();
++       openlog("atd", LOG_PID, LOG_ATD);
++#endif
++
++   mail_pid = fork();
+ 
++   if ( mail_pid == 0 )
++   {
+ 	PRIV_START
+ 
+ 	    if (initgroups(pentry->pw_name, pentry->pw_gid))
+@@ -535,7 +539,21 @@ run_file(const char *filename, uid_t uid
+ 	    perr("Exec failed for mail command");
+ 
+ 	PRIV_END
++   }
++   else if ( mail_pid == -1 ) {
++           perr("fork of mailer failed");
++   }
++   else {
++           /* Parent */
++           waitpid(mail_pid, (int *) NULL, 0);
++   }
++#ifdef WITH_PAM
++   AT_CLOSE_PAM;
++   closelog();
++   openlog("atd", LOG_PID, LOG_ATD);
++#endif
+     }
++#endif
+     exit(EXIT_SUCCESS);
+ }
+ 
+diff -up at-3.1.13/config.h.in.pam at-3.1.13/config.h.in
+--- at-3.1.13/config.h.in.pam	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/config.h.in	2012-04-19 16:50:57.506000001 +0200
+@@ -68,8 +68,8 @@
+ /* Define to 1 if you have the <nlist.h> header file. */
+ #undef HAVE_NLIST_H
+ 
+-/* Define to 1 for PAM support */
+-#undef HAVE_PAM
++/* Define if you are building with_pam */
++#undef WITH_PAM
+ 
+ /* Define to 1 if you have the `pstat_getdynamic' function. */
+ #undef HAVE_PSTAT_GETDYNAMIC
+diff -up at-3.1.13/configure.ac.pam at-3.1.13/configure.ac
+--- at-3.1.13/configure.ac.pam	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/configure.ac	2012-04-19 16:50:57.506000001 +0200
+@@ -84,7 +84,7 @@ AC_FUNC_GETLOADAVG
+ AC_CHECK_FUNCS(getcwd mktime strftime setreuid setresuid sigaction waitpid)
+ AC_CHECK_HEADERS(security/pam_appl.h, [
+   PAMLIB="-lpam"
+-  AC_DEFINE(HAVE_PAM, 1, [Define to 1 for PAM support])
++  AC_DEFINE(WITH_PAM, 1, [Define to 1 for PAM support])
+ ])
+ 
+ dnl Checking for programs
+@@ -238,6 +238,13 @@ AC_ARG_WITH(daemon_username,
+ )
+ AC_SUBST(DAEMON_USERNAME)
+ 
++AC_ARG_WITH(pam,
++[ --with-pam            Define to enable pam support ],
++AC_DEFINE(WITH_PAM),
++)
++AC_CHECK_LIB(pam, pam_start, PAMLIB='-lpam -lpam_misc')
++AC_SUBST(PAMLIB)
++
+ AC_MSG_CHECKING(groupname to run under)
+ AC_ARG_WITH(daemon_groupname,
+ [ --with-daemon_groupname=DAEMON_GROUPNAME	Groupname to run under (default daemon) ],
+diff -up at-3.1.13/perm.c.pam at-3.1.13/perm.c
+--- at-3.1.13/perm.c.pam	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/perm.c	2012-04-19 16:53:09.192001742 +0200
+@@ -51,6 +51,14 @@
+ #define PRIV_END while(0)
+ #endif
+ 
++#ifdef WITH_PAM
++#include <security/pam_appl.h>
++static pam_handle_t *pamh = NULL;
++static const struct pam_conv conv = {
++       NULL
++};
++#endif
++
+ /* Structures and unions */
+ 
+ 
+@@ -108,18 +116,45 @@ user_in_file(const char *path, const cha
+ int
+ check_permission()
+ {
+-  uid_t uid = geteuid();
++  uid_t euid = geteuid(), uid=getuid(), egid=getegid(), gid=getgid();
+   struct passwd *pentry;
+   int    allow = 0, deny = 1;
+ 
+-  if (uid == 0)
++  int    retcode = 0;
++  if (euid == 0)
+     return 1;
+ 
+-  if ((pentry = getpwuid(uid)) == NULL) {
++  if ((pentry = getpwuid(euid)) == NULL) {
+     perror("Cannot access user database");
+     exit(EXIT_FAILURE);
+   }
+ 
++#ifdef  WITH_PAM
++/*
++ *  We must check if the atd daemon userid will be allowed to gain the job owner user's
++ *  credentials with PAM . If not, the user has been denied at(1) usage, eg. with pam_access.
++ */
++  if (setreuid(daemon_uid, daemon_uid) != 0) {
++      fprintf(stderr, "cannot set egid: %s", strerror(errno));
++      exit(1);
++  }
++  if (setregid(daemon_gid, daemon_gid) != 0) {
++      fprintf(stderr, "cannot set euid: %s", strerror(errno));
++      exit(1);
++  }
++
++    AT_START_PAM;
++    AT_CLOSE_PAM;
++    if (setregid(gid,egid) != 0) {
++        fprintf(stderr, "cannot set egid: %s", strerror(errno));
++        exit(1);
++    }
++    if (setreuid(uid,euid) != 0) {
++        fprintf(stderr, "cannot set euid: %s", strerror(errno));
++        exit(1);
++    }
++#endif
++
+   allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name);
+   if (allow==0 || allow==1)
+     return allow;
+diff -up at-3.1.13/privs.h.pam at-3.1.13/privs.h
+--- at-3.1.13/privs.h.pam	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/privs.h	2012-04-19 16:53:46.296016675 +0200
+@@ -144,3 +144,63 @@ extern gid_t real_gid, effective_gid, da
+ #error "Cannot implement user ID swapping without setreuid or setresuid"
+ #endif
+ #endif
++
++#ifdef WITH_PAM
++/* PAM failed after session was open.  */
++#define PAM_SESSION_FAIL if (retcode != PAM_SUCCESS) \
++       pam_close_session(pamh,PAM_SILENT);
++
++/* syslog will be logging error messages */
++#ifdef HAVE_UNISTD_H
++#include <syslog.h>
++#endif
++
++/* PAM fail even before opening the session */
++#define PAM_FAIL_CHECK \
++       do { if (retcode != PAM_SUCCESS) { \
++               fprintf(stderr,"PAM failure: %s\n",pam_strerror(pamh, retcode)); \
++               syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
++               if (pamh) \
++                   pam_end(pamh, retcode); \
++               if (setregid(getgid(),getegid()) != 0) { \
++                   fprintf(stderr, "cannot set egid: %s", strerror(errno)); \
++                   exit(1); \
++               } \
++               if (setreuid(getuid(),geteuid()) != 0) { \
++                   fprintf(stderr, "cannot set euid: %s", strerror(errno)); \
++                   exit(1); \
++               } \
++               exit(1); \
++           } \
++       } while (0) \
++
++static int pam_session_opened = 0;      //global for open session
++
++#define AT_START_PAM { \
++        retcode = pam_start("atd", pentry->pw_name, &conv, &pamh); \
++        PAM_FAIL_CHECK; \
++        retcode = pam_set_item(pamh, PAM_TTY, "atd"); \
++        PAM_FAIL_CHECK; \
++        retcode = pam_acct_mgmt(pamh, PAM_SILENT); \
++        PAM_FAIL_CHECK; \
++} 
++
++#define AT_OPEN_PAM_SESSION { \
++        retcode = pam_open_session(pamh, PAM_SILENT); \
++        PAM_FAIL_CHECK; \
++        retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); \
++        PAM_FAIL_CHECK; \
++        if (retcode == PAM_SUCCESS) \
++                pam_session_opened = 1; \
++}
++
++#define AT_CLOSE_PAM { \
++        if (pam_session_opened != 0) { \
++                pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT); \
++                pam_close_session(pamh, PAM_SILENT); \
++        } \
++        pam_end(pamh, PAM_SUCCESS); \
++}
++
++#endif
++
diff --git a/SOURCES/at-3.1.13-selinux.patch b/SOURCES/at-3.1.13-selinux.patch
new file mode 100644
index 0000000..255fe2b
--- /dev/null
+++ b/SOURCES/at-3.1.13-selinux.patch
@@ -0,0 +1,165 @@
+diff -up at-3.1.13/atd.c.selinux at-3.1.13/atd.c
+--- at-3.1.13/atd.c.selinux	2012-11-01 15:11:21.368772308 +0100
++++ at-3.1.13/atd.c	2012-11-01 15:13:16.809162818 +0100
+@@ -83,6 +83,14 @@
+ #include "getloadavg.h"
+ #endif
+ 
++#ifdef WITH_SELINUX
++#include <selinux/selinux.h>
++#include <selinux/get_context_list.h>
++int selinux_enabled=0;
++#include <selinux/flask.h>
++#include <selinux/av_permissions.h>
++#endif
++
+ #ifndef LOG_ATD
+ #define LOG_ATD        LOG_DAEMON
+ #endif
+@@ -202,6 +210,68 @@ myfork()
+ #define ATD_MAIL_NAME    "mailx"
+ #endif
+ 
++#ifdef WITH_SELINUX
++static int set_selinux_context(const char *name, const char *filename) {
++       security_context_t user_context=NULL;
++       security_context_t  file_context=NULL;
++       struct av_decision avd;
++       int retval=-1;
++       char *seuser=NULL;
++       char *level=NULL;
++
++       if (getseuserbyname(name, &seuser, &level) == 0) {
++               retval=get_default_context_with_level(seuser, level, NULL, &user_context);
++               free(seuser);
++               free(level);
++               if (retval) {
++                       if (security_getenforce()==1) {
++                               perr("execle: couldn't get security context for user %s\n", name);
++                       } else {
++                               syslog(LOG_ERR, "execle: couldn't get security context for user %s\n", name);
++                               return -1;
++                       }
++               }
++       }
++
++       /*
++       * Since crontab files are not directly executed,
++       * crond must ensure that the crontab file has
++       * a context that is appropriate for the context of
++       * the user cron job.  It performs an entrypoint
++       * permission check for this purpose.
++       */
++       if (fgetfilecon(STDIN_FILENO, &file_context) < 0)
++               perr("fgetfilecon FAILED %s", filename);
++
++       retval = security_compute_av(user_context,
++                                    file_context,
++                                    SECCLASS_FILE,
++                                    FILE__ENTRYPOINT,
++                                    &avd);
++       freecon(file_context);
++       if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) {
++               if (security_getenforce()==1) {
++                       perr("Not allowed to set exec context to %s for user  %s\n", user_context,name);
++               } else {
++                       syslog(LOG_ERR, "Not allowed to set exec context to %s for user  %s\n", user_context,name);
++                       retval = -1;
++                       goto err;
++               }
++       }
++       if (setexeccon(user_context) < 0) {
++               if (security_getenforce()==1) {
++                       perr("Could not set exec context to %s for user  %s\n", user_context,name);
++                       retval = -1;
++               } else {
++                       syslog(LOG_ERR, "Could not set exec context to %s for user  %s\n", user_context,name);
++               }
++       }
++  err:
++       freecon(user_context);
++       return 0;
++}
++#endif
++
+ static void
+ run_file(const char *filename, uid_t uid, gid_t gid)
+ {
+@@ -446,9 +516,23 @@ run_file(const char *filename, uid_t uid
+ 		perr("Cannot reset signal handler to default");
+ 
+ 	    chdir("/");
+-
++#ifdef WITH_SELINUX
++            if (selinux_enabled > 0) {
++                if (set_selinux_context(pentry->pw_name, filename) < 0)
++                       perr("SELinux Failed to set context\n");
++            }
++#endif
+ 	    if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0)
+ 		perr("Exec failed for /bin/sh");
++//add for fedora
++#ifdef WITH_SELINUX
++               if (selinux_enabled>0)
++                       if (setexeccon(NULL) < 0)
++                               if (security_getenforce()==1)
++                                       perr("Could not resset exec context for user %s\n", pentry->pw_name);
++#endif
++//end
++//add for fedora
+ #ifdef  WITH_PAM
+ 	    if ( ( nenvp != &nul ) && (pam_envp != 0L)  && (*pam_envp != 0L))
+ 	    {
+@@ -751,6 +835,10 @@ main(int argc, char *argv[])
+     struct passwd *pwe;
+     struct group *ge;
+ 
++#ifdef WITH_SELINUX
++    selinux_enabled=is_selinux_enabled();
++#endif
++
+ /* We don't need root privileges all the time; running under uid and gid
+  * daemon is fine.
+  */
+diff -up at-3.1.13/config.h.in.selinux at-3.1.13/config.h.in
+--- at-3.1.13/config.h.in.selinux	2012-11-01 15:11:21.368772308 +0100
++++ at-3.1.13/config.h.in	2012-11-01 15:11:21.371772392 +0100
+@@ -71,6 +71,9 @@
+ /* Define if you are building with_pam */
+ #undef WITH_PAM
+ 
++/* Define if you are building with_selinux  */
++#undef WITH_SELINUX
++
+ /* Define to 1 if you have the `pstat_getdynamic' function. */
+ #undef HAVE_PSTAT_GETDYNAMIC
+ 
+diff -up at-3.1.13/configure.ac.selinux at-3.1.13/configure.ac
+--- at-3.1.13/configure.ac.selinux	2012-11-01 15:11:21.369772335 +0100
++++ at-3.1.13/configure.ac	2012-11-01 15:11:21.372772420 +0100
+@@ -266,5 +266,13 @@ AC_ARG_WITH(daemon_groupname,
+ )
+ AC_SUBST(DAEMON_GROUPNAME)
+ 
++AC_ARG_WITH(selinux,
++[ --with-selinux       Define to run with selinux],
++AC_DEFINE(WITH_SELINUX),
++)
++AC_CHECK_LIB(selinux, is_selinux_enabled, SELINUXLIB=-lselinux)
++AC_SUBST(SELINUXLIB)
++AC_SUBST(WITH_SELINUX)
++
+ AC_CONFIG_FILES(Makefile atrun atd.8 atrun.8 at.1 at.allow.5 batch)
+ AC_OUTPUT
+diff -up at-3.1.13/Makefile.in.selinux at-3.1.13/Makefile.in
+--- at-3.1.13/Makefile.in.selinux	2012-11-01 15:11:21.361772115 +0100
++++ at-3.1.13/Makefile.in	2012-11-01 15:11:21.372772420 +0100
+@@ -39,6 +39,8 @@ LIBS		= @LIBS@
+ LIBOBJS		= @LIBOBJS@
+ INSTALL		= @INSTALL@
+ PAMLIB          = @PAMLIB@
++SELINUXLIB      = @SELINUXLIB@
++
+ 
+ CLONES		= atq atrm
+ ATOBJECTS	= at.o panic.o perm.o posixtm.o y.tab.o lex.yy.o
diff --git a/SOURCES/at-3.1.13-usePOSIXtimers.patch b/SOURCES/at-3.1.13-usePOSIXtimers.patch
new file mode 100644
index 0000000..018bae2
--- /dev/null
+++ b/SOURCES/at-3.1.13-usePOSIXtimers.patch
@@ -0,0 +1,119 @@
+diff -ur -x configure at-3.1.13.orig/atd.c at-3.1.13/atd.c
+--- at-3.1.13.orig/atd.c	2011-11-16 11:30:22.424764253 -0500
++++ at-3.1.13/atd.c	2011-11-16 16:41:12.102831656 -0500
+@@ -815,6 +815,54 @@
+     return next_job;
+ }
+ 
++#ifdef HAVE_CLOCK_GETTIME
++timer_t timer;
++struct itimerspec timeout;
++
++void timer_setup()
++{
++    struct sigevent sev;
++
++    sev.sigev_notify = SIGEV_SIGNAL;
++    sev.sigev_signo = SIGHUP;
++    sev.sigev_value.sival_ptr = &timer;
++
++    memset(&timeout, 0, sizeof(timeout));
++
++    if (timer_create(CLOCK_REALTIME, &sev, &timer) < 0)
++	    pabort("unable to create timer");
++}
++
++time_t atd_gettime()
++{
++    struct timespec curtime;
++
++    clock_gettime(CLOCK_REALTIME, &curtime);
++
++    return curtime.tv_sec;
++}
++
++void atd_setalarm(time_t next)
++{
++    timeout.it_value.tv_sec = next;
++    timer_settime(timer, TIMER_ABSTIME, &timeout, NULL);
++    pause();
++}
++#else
++void timer_setup()
++{
++}
++
++time_t atd_gettime()
++{
++    return time(NULL);
++}
++
++void atd_setalarm(time_t next)
++{
++    sleep(next - atd_gettime());
++}
++#endif
+ /* Global functions */
+ 
+ int
+@@ -835,7 +883,6 @@
+     struct sigaction act;
+     struct passwd *pwe;
+     struct group *ge;
+-
+ #ifdef WITH_SELINUX
+     selinux_enabled=is_selinux_enabled();
+ #endif
+@@ -912,7 +959,7 @@
+     sigaction(SIGCHLD, &act, NULL);
+ 
+     if (!run_as_daemon) {
+-	now = time(NULL);
++	now = atd_gettime();
+ 	run_loop();
+ 	exit(EXIT_SUCCESS);
+     }
+@@ -935,13 +982,15 @@
+     act.sa_handler = set_term;
+     sigaction(SIGINT, &act, NULL);
+ 
++    timer_setup();
++
+     daemon_setup();
+ 
+     do {
+-	now = time(NULL);
++	now = atd_gettime();
+ 	next_invocation = run_loop();
+ 	if (next_invocation > now) {
+-	    sleep(next_invocation - now);
++	    atd_setalarm(next_invocation);
+ 	}
+     } while (!term_signal);
+     daemon_cleanup();
+diff -ur -x configure at-3.1.13.orig/config.h.in at-3.1.13/config.h.in
+--- at-3.1.13.orig/config.h.in	2011-11-16 11:30:22.424764253 -0500
++++ at-3.1.13/config.h.in	2011-11-16 16:32:44.485426754 -0500
+@@ -38,6 +38,9 @@
+ /* Define to 1 if you have the `getloadavg' function. */
+ #undef HAVE_GETLOADAVG
+ 
++/* Define to 1 if you have the `clock_gettime' function. */
++#undef HAVE_TIMER_CREATE
++
+ /* Define to 1 if you have the <getopt.h> header file. */
+ #undef HAVE_GETOPT_H
+ 
+diff -ur -x configure at-3.1.13.orig/configure.ac at-3.1.13/configure.ac
+--- at-3.1.13.orig/configure.ac	2011-11-16 11:30:22.425764254 -0500
++++ at-3.1.13/configure.ac	2011-11-16 16:31:29.791561747 -0500
+@@ -274,5 +274,9 @@
+ AC_SUBST(SELINUXLIB)
+ AC_SUBST(WITH_SELINUX)
+ 
++dnl check for POSIX timer functions
++AC_SEARCH_LIBS([timer_create],[rt])
++AC_CHECK_FUNCS([timer_create])
++
+ AC_CONFIG_FILES(Makefile atrun atd.8 atrun.8 at.1 at.allow.5 batch)
+ AC_OUTPUT
diff --git a/SOURCES/at-3.1.13-utc-dst.patch b/SOURCES/at-3.1.13-utc-dst.patch
new file mode 100644
index 0000000..1f72c39
--- /dev/null
+++ b/SOURCES/at-3.1.13-utc-dst.patch
@@ -0,0 +1,24 @@
+diff -up at-3.1.13/parsetime.y.dst at-3.1.13/parsetime.y
+--- at-3.1.13/parsetime.y.dst	2011-06-25 14:43:14.000000000 +0200
++++ at-3.1.13/parsetime.y	2016-04-20 17:23:24.140171655 +0200
+@@ -476,8 +476,8 @@ parsetime(time_t currtime, int argc, cha
+     exectm = *localtime(&currtime);
+     currtime -= exectm.tm_sec;
+     exectm.tm_sec = 0;
+-    exectm.tm_isdst = -1;
+     memcpy(&currtm,&exectm,sizeof(currtm));
++    exectm.tm_isdst = -1;
+     time_only = 0;
+     yearspec = 0;
+ 
+@@ -503,8 +503,8 @@ parsetime(time_t currtime, int argc, cha
+ 	    return 0;
+ 	if (isgmt) {
+ 	    exectime -= timezone;
+-	    if (currtm.tm_isdst && !exectm.tm_isdst)
+-		exectime -= 3600;
++	    if (exectm.tm_isdst)
++		exectime += 3600;
+ 	}
+ 	if (exectime < currtime)
+ 		panic("refusing to create job destined in the past");
diff --git a/SOURCES/atd.init b/SOURCES/atd.init
new file mode 100755
index 0000000..2f3fd20
--- /dev/null
+++ b/SOURCES/atd.init
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# atd Starts/stop the "at" daemon
+#
+# chkconfig:   345 95 5
+# description: Runs commands scheduled by the "at" command at the time \
+#    specified when "at" was run, and runs batch commands when the load \
+#    average is low enough.
+
+### BEGIN INIT INFO
+# Provides: atd at batch
+# Required-Start: $local_fs
+# Required-Stop: $local_fs
+# Default-Start: 345
+# Default-Stop: 95
+# Short-Description: Starts/stop the "at" daemon
+# Description:      Runs commands scheduled by the "at" command at the time 
+#    specified when "at" was run, and runs batch commands when the load 
+#    average is low enough.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+exec=/usr/sbin/atd
+prog="atd"
+config=/etc/sysconfig/atd
+
+[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
+
+lockfile=/var/lock/subsys/$prog
+
+start() {
+    [ -x $exec ] || exit 5
+    [ -f $config ] || exit 6
+    echo -n $"Starting $prog: "
+    daemon $exec $OPTS && success || failure
+    retval=$?
+    echo
+    [ $retval -eq 0 ] && touch $lockfile
+    return $retval
+}
+
+stop() {
+    echo -n $"Stopping $prog: "
+    if [ -n "`pidfileofproc $exec`" ] ; then
+        killproc $exec
+		RETVAL=3
+    else
+        failure $"Stopping $prog"
+    fi
+    retval=$?
+    echo
+    [ $retval -eq 0 ] && rm -f $lockfile
+    return $retval
+}
+
+restart() {
+    stop
+    start
+}
+
+reload() {
+    restart
+}
+
+force_reload() {
+    restart
+}
+
+rh_status() {
+    # run checks to determine if the service is running or use generic status
+    status $prog
+}
+
+rh_status_q() {
+    rh_status >/dev/null 2>&1
+}
+
+
+case "$1" in
+    start)
+        rh_status_q && exit 0
+        $1
+        ;;
+    stop)
+        rh_status_q || exit 0
+        $1
+        ;;
+    restart)
+        $1
+        ;;
+    reload)
+        rh_status_q || exit 7
+        $1
+        ;;
+    force-reload)
+        force_reload
+        ;;
+    status)
+        rh_status
+        ;;
+    condrestart|try-restart)
+        rh_status_q || exit 0
+        restart
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+        exit 2
+esac
+exit $?
diff --git a/SOURCES/atd.sysconf b/SOURCES/atd.sysconf
new file mode 100644
index 0000000..056ce81
--- /dev/null
+++ b/SOURCES/atd.sysconf
@@ -0,0 +1,9 @@
+# specify additional command line arguments for atd
+#
+# -l Specifies  a  limiting  load  factor,  over which batch jobs should not be run, instead of the compile-time
+#    choice of 0.8.  For an SMP system with n CPUs, you will probably want to set this higher than n-1.
+# 
+#  -b Specifiy the minimum interval in seconds between the start of two batch jobs (60 default).
+
+#example: 
+#OPTS="-l 4 -b 120"
diff --git a/SOURCES/atd.systemd b/SOURCES/atd.systemd
new file mode 100644
index 0000000..abe24c1
--- /dev/null
+++ b/SOURCES/atd.systemd
@@ -0,0 +1,11 @@
+[Unit]
+Description=Job spooling tools
+After=syslog.target systemd-user-sessions.service
+
+[Service]
+EnvironmentFile=/etc/sysconfig/atd
+ExecStart=/usr/sbin/atd -f $OPTS
+IgnoreSIGPIPE=no
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SOURCES/pam_atd b/SOURCES/pam_atd
new file mode 100644
index 0000000..1fd529e
--- /dev/null
+++ b/SOURCES/pam_atd
@@ -0,0 +1,9 @@
+# The PAM configuration file for the at daemon
+#
+#
+auth       required    pam_env.so
+auth       include     password-auth
+account    required    pam_access.so
+account    include     password-auth
+session    required    pam_loginuid.so
+session    include     password-auth
diff --git a/SPECS/at.spec b/SPECS/at.spec
new file mode 100644
index 0000000..d206aec
--- /dev/null
+++ b/SPECS/at.spec
@@ -0,0 +1,263 @@
+%bcond_without pam
+%global _hardened_build 1
+
+Summary:	Job spooling tools
+Name:		at
+Version:	3.1.13
+Release:	22%{?dist}.2
+# http://packages.debian.org/changelogs/pool/main/a/at/current/copyright
+# + install-sh is MIT license with changes under Public Domain
+License:	GPLv3+ and GPLv2+ and ISC and MIT and Public Domain
+Group:		System Environment/Daemons
+URL:		http://ftp.debian.org/debian/pool/main/a/at
+
+Source:		http://ftp.debian.org/debian/pool/main/a/at/at_%{version}.orig.tar.gz
+# git upstream source git://git.debian.org/git/collab-maint/at.git
+Source1:	pam_atd
+Source2:	atd.init
+Source3:	atd.sysconf
+Source5:	atd.systemd
+
+Patch1:		at-3.1.13-makefile.patch
+Patch2:		at-3.1.12-opt_V.patch
+Patch3:		at-3.1.12-shell.patch
+Patch4:		at-3.1.13-nitpicks.patch
+Patch5:		at-3.1.13-pam.patch
+Patch6:		at-3.1.13-selinux.patch
+Patch7:		at-3.1.12-nowrap.patch
+Patch8:		at-3.1.12-fix_no_export.patch 
+Patch9:         at-3.1.13-mailwithhostname.patch
+Patch10:        at-3.1.13-usePOSIXtimers.patch
+Patch11:        at-3.1.13-help.patch
+Patch12:        at-3.1.10-filter-environment.patch
+Patch13:	at-3.1.13-fclose-error.patch
+Patch14:	at-3.1.13-clear-nonjobs.patch
+Patch15:	at-3.1.13-utc-dst.patch
+Patch17:	at-3.1.13-aborted-jobs.patch
+
+BuildRequires: fileutils /etc/init.d
+BuildRequires: flex flex-static bison autoconf
+BuildRequires: libselinux-devel >= 1.27.9
+BuildRequires: perl(Test::Harness)
+BuildRequires: perl(Test::More)
+
+%if %{with pam}
+BuildRequires: pam-devel
+%endif
+Conflicts: crontabs <= 1.5
+# No, I'm not kidding
+BuildRequires: smtpdaemon
+
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+
+%description
+At and batch read commands from standard input or from a specified
+file. At allows you to specify that a command will be run at a
+particular time. Batch will execute commands when the system load
+levels drop to a particular level. Both commands use user's shell.
+
+You should install the at package if you need a utility for
+time-oriented job control. Note: If it is a recurring job that will
+need to be repeated at the same time every day/week, etc. you should
+use crontab instead.
+
+%package sysvinit
+Summary:	SysV init script for at
+Group:		System Environment/Base
+Requires:	%{name} = %{version}-%{release}
+Requires(post): /sbin/chkconfig
+
+%description sysvinit
+SysV style init script for at. It needs to be installed only if systemd
+is not used as the system init process.
+
+%prep
+%setup -q
+cp %{SOURCE1} .
+%patch1 -p1 -b .make
+%patch2 -p1 -b .opt_V
+%patch3 -p1 -b .shell
+%patch4 -p1 -b .nit
+%patch5 -p1 -b .pam
+%patch6 -p1 -b .selinux
+%patch7 -p1 -b .nowrap
+%patch8 -p1 -b .export
+%patch9 -p1 -b .mail
+%patch10 -p1 -b .posix
+%patch11 -p1 -b .help
+%patch12 -p1 -b .filter-environment
+%patch13 -p1 -b .fclose
+%patch14 -p1 -b .clear-nonjobs
+%patch15 -p1 -b .dst
+%patch17 -p1 -b .aborted-jobs
+
+%build
+# patch9 touches configure.in
+autoconf
+# clean old pregenerated files
+rm -f lex.yy.* y.tab.*
+%configure --with-atspool=%{_localstatedir}/spool/at/spool \
+	--with-jobdir=%{_localstatedir}/spool/at \
+	--with-daemon_username=root  \
+	--with-daemon_groupname=root \
+	--with-selinux \
+%if %{with pam}
+	--with-pam
+%endif
+
+make
+
+%install
+make install \
+	DAEMON_USERNAME=`id -nu`\
+	DAEMON_GROUPNAME=`id -ng` \
+	DESTDIR=%{buildroot}\
+	sbindir=%{buildroot}%{_prefix}/sbin\
+	bindir=%{buildroot}%{_bindir}\
+	prefix=%{buildroot}%{_prefix}\
+	exec_prefix=%{buildroot}%{_prefix}\
+	docdir=%{buildroot}/usr/doc\
+	mandir=%{buildroot}%{_mandir}\
+	etcdir=%{buildroot}%{_sysconfdir} \
+	ATJOB_DIR=%{buildroot}%{_localstatedir}/spool/at \
+	ATSPOOL_DIR=%{buildroot}%{_localstatedir}/spool/at/spool \
+	INSTALL_ROOT_USER=`id -nu` \
+	INSTALL_ROOT_GROUP=`id -nu`;
+
+echo > %{buildroot}%{_sysconfdir}/at.deny
+mkdir docs
+cp  %{buildroot}/%{_prefix}/doc/at/* docs/
+
+mkdir -p %{buildroot}%{_sysconfdir}/pam.d
+install -m 644 %{SOURCE1} %{buildroot}%{_sysconfdir}/pam.d/atd
+
+mkdir -p %{buildroot}%{_sysconfdir}/rc.d/init.d
+install -m 755 %{SOURCE2} %{buildroot}%{_sysconfdir}/rc.d/init.d/atd
+
+mkdir -p %{buildroot}/etc/sysconfig
+install -m 644 %{SOURCE3} %{buildroot}/etc/sysconfig/atd
+
+# install systemd initscript
+mkdir -p %{buildroot}/%{_unitdir}/
+install -m 644 %{SOURCE5} %{buildroot}/%{_unitdir}/atd.service
+
+# remove unpackaged files from the buildroot
+rm -r  %{buildroot}%{_prefix}/doc
+
+%check
+make test
+
+%post
+touch %{_localstatedir}/spool/at/.SEQ
+chmod 600 %{_localstatedir}/spool/at/.SEQ
+chown daemon:daemon %{_localstatedir}/spool/at/.SEQ
+%systemd_post atd.service
+
+%preun
+%systemd_preun atd.service
+
+%postun
+%systemd_postun_with_restart atd.service
+
+%triggerun -- at < 3.1.12-6
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply atd
+# to migrate them to systemd targets
+/usr/bin/systemd-sysv-convert --save atd
+
+# The package is allowed to autostart:
+/bin/systemctl enable atd.service >/dev/null 2>&1
+
+/sbin/chkconfig --del atd >/dev/null 2>&1 || :
+/bin/systemctl try-restart atd.service >/dev/null 2>&1 || :
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+
+%triggerpostun -n at-sysvinit -- at < 3.1.12-9
+/sbin/chkconfig --add atd >/dev/null 2>&1 || :
+
+%files
+%doc docs/*
+%attr(0644,root,root)		%config(noreplace) %{_sysconfdir}/at.deny
+%attr(0644,root,root)		%config(noreplace) %{_sysconfdir}/sysconfig/atd
+%attr(0700,daemon,daemon)	%dir %{_localstatedir}/spool/at
+%attr(0600,daemon,daemon)	%verify(not md5 size mtime) %ghost %{_localstatedir}/spool/at/.SEQ
+%attr(0700,daemon,daemon)	%dir %{_localstatedir}/spool/at/spool
+%attr(0644,root,root)		%config(noreplace) %{_sysconfdir}/pam.d/atd
+%{_sbindir}/atrun
+%attr(0755,root,root)		%{_sbindir}/atd
+%{_mandir}/man*/*
+%{_bindir}/batch
+%{_bindir}/atrm
+%{_bindir}/atq
+%attr(4755,root,root)		%{_bindir}/at
+%attr(0644,root,root)		/%{_unitdir}/atd.service
+
+%files sysvinit
+%attr(0755,root,root)		%{_initrddir}/atd
+
+%changelog
+* Wed Dec 20 2017 Tomáš Mráz <tmraz@redhat.com> - 3.1.13-22.2
+- fix handling of the aborted jobs (due to possibly
+  temporary conditions) and avoid flooding the syslog
+
+* Mon May 23 2016 Tomáš Mráz <tmraz@redhat.com> - 3.1.13-22
+- SIGPIPE should not be ignored in atd (#1338039)
+
+* Wed Apr 20 2016 Tomáš Mráz <tmraz@redhat.com> - 3.1.13-21
+- correct the DST correction when using UTC time specification (#1328832)
+- clear non-job files from at dir and test for write error on fclose
+  to fix bogus syslog messages
+
+* Mon Jun 22 2015 Tomáš Mráz <tmraz@redhat.com> - 3.1.13-20
+- build the package with hardening flags (PIE, full RELRO)
+
+* Fri Oct  3 2014 Tomáš Mráz <tmraz@redhat.com> - 3.1.13-18
+- filter environment variables not acceptable in bash input
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 3.1.13-17
+- Mass rebuild 2014-01-24
+
+* Thu Jan 09 2014 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-16
+- the correct solution is remove smp_flags, they don't work properly on ppc with
+  the option mpower7
+- Related: rhbz#1048745
+
+* Mon Jan 06 2014 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-15
+- remove old changelogs
+- ppc fail to rebuild package
+- Resolves: rhbz#1048745
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 3.1.13-14
+- Mass rebuild 2013-12-27
+
+* Thu Jul 11 2013 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-13
+- rebuild with ? in dist
+- Resolves: rhbz#983255
+
+* Mon Feb 11 2013 Peter Robinson <pbrobinson@fedoraproject.org> 3.1.13-12
+- Fix patch to fix FTBFS with gcc 4.8
+
+* Wed Nov 14 2012 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-11
+- fix license field again
+
+* Thu Nov  1 2012 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-10
+- fix license field
+- fix systemd macros in scriptlets part of the specfile
+- fix selinux patch to apply without fuzz=2
+
+* Fri Jul 27 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.1.13-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Tue Apr 17 2012 Marcela Mašláňová <mmaslano@redhat.com> - 3.1.13-8
+- at-3.1.13-mailwithhostname.patch in email mention also hostname address
+- at-3.1.13-usePOSIXtimers.patch use POSIX timers, so we won't need
+  pm-utils hack anymore
+- at-3.1.13-help.patch update usage
+- systemd-user-sessions.service is used in unit file, so the atd should be
+  started after almost all services are up and running
+- 812682 pam support work with new systemd defaults
+
+* Thu Jan 12 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.1.13-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild