From 92956ea3adbd2d28876409531cf890251bde86ee Mon Sep 17 00:00:00 2001 From: Marcela Mašláňová Date: Jul 29 2011 12:27:23 +0000 Subject: Update to 3.1.13. --- diff --git a/at-3.1.13-makefile.patch b/at-3.1.13-makefile.patch new file mode 100644 index 0000000..e429719 --- /dev/null +++ b/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) -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) -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" 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/at-3.1.13-nitpicks.patch b/at-3.1.13-nitpicks.patch new file mode 100644 index 0000000..d9174c0 --- /dev/null +++ b/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/at-3.1.13-pam.patch b/at-3.1.13-pam.patch new file mode 100644 index 0000000..e4cae11 --- /dev/null +++ b/at-3.1.13-pam.patch @@ -0,0 +1,430 @@ +diff -up at-3.1.13/at.c.pam at-3.1.13/at.c +--- at-3.1.13/at.c.pam 2011-07-29 13:51:50.234127938 +0200 ++++ at-3.1.13/at.c 2011-07-29 13:51:50.245127883 +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 2011-07-29 13:51:50.240127908 +0200 ++++ at-3.1.13/atd.c 2011-07-29 13:54:35.805384873 +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 + + 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,10 @@ 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 ++ PAM_HANDLING; ++ closelog(); ++ openlog("atd", LOG_PID, LOG_ATD); + #endif + + close(STDIN_FILENO); +@@ -419,7 +404,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 +430,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 +448,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 +470,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 +500,19 @@ 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 ++ PAM_HANDLING; ++ 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 +537,23 @@ 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 ++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); ++ pam_close_session(pamh, PAM_SILENT); ++ pam_end(pamh, PAM_ABORT); ++ 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 2011-07-29 13:51:50.246127878 +0200 +@@ -68,8 +68,8 @@ + /* Define to 1 if you have the 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 2011-07-29 13:51:50.247127873 +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 2011-07-29 13:51:50.248127868 +0200 +@@ -51,6 +51,14 @@ + #define PRIV_END while(0) + #endif + ++#ifdef WITH_PAM ++#include ++static pam_handle_t *pamh = NULL; ++static const struct pam_conv conv = { ++ NULL ++}; ++#endif ++ + /* Structures and unions */ + + +@@ -108,18 +116,51 @@ 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); ++ } ++ ++ pam_close_session(pamh,PAM_SILENT); ++ ++ PAM_HANDLING; ++ ++ pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT ); ++ pam_close_session(pamh,PAM_SILENT); ++ pam_end(pamh, PAM_ABORT); ++ ++ 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 2011-07-29 13:51:50.248127868 +0200 +@@ -144,3 +144,61 @@ 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 ++#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) \ ++ ++/* PAM - check after every operation whether they passed */ ++#define PAM_HANDLING \ ++ do { pamh = NULL; \ ++ 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; \ ++ retcode = pam_open_session(pamh, PAM_SILENT); \ ++ PAM_FAIL_CHECK; \ ++ retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); \ ++ PAM_SESSION_FAIL; \ ++ PAM_FAIL_CHECK; \ ++ } while (0) ++ ++/* OLD FAIL_CHECK ONLY FOR perm.c ++ * define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ ++ * fprintf(stderr,"\nPAM failure %s\n",pam_strerror(pamh, retcode)); \ ++ * syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ ++ * if (pamh) \ ++ * pam_end(pamh, retcode); \ ++ * exit(1); \ ++ * } ++ */ ++ ++#endif ++ diff --git a/at-3.1.13-selinux.patch b/at-3.1.13-selinux.patch new file mode 100644 index 0000000..0fcaff1 --- /dev/null +++ b/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 2011-07-29 13:58:54.282221007 +0200 ++++ at-3.1.13/atd.c 2011-07-29 14:02:46.563175313 +0200 +@@ -83,6 +83,14 @@ + #include "getloadavg.h" + #endif + ++#ifdef WITH_SELINUX ++#include ++#include ++int selinux_enabled=0; ++#include ++#include ++#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) + { +@@ -445,9 +515,24 @@ 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 +836,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 2011-07-29 13:58:54.283221003 +0200 ++++ at-3.1.13/config.h.in 2011-07-29 13:58:54.289220979 +0200 +@@ -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 2011-07-29 13:58:54.284220999 +0200 ++++ at-3.1.13/configure.ac 2011-07-29 13:58:54.290220975 +0200 +@@ -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 2011-07-29 13:58:54.270221055 +0200 ++++ at-3.1.13/Makefile.in 2011-07-29 13:58:54.290220975 +0200 +@@ -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/at.spec b/at.spec index 3418b28..da563f2 100644 --- a/at.spec +++ b/at.spec @@ -1,32 +1,28 @@ -# needed because of _ in upstream tarball -%define major_ver 3.1.12 - %bcond_without pam Summary: Job spooling tools Name: at -Version: %{major_ver} -Release: 11%{dist} +Version: 3.1.13 +Release: 1%{dist} License: GPLv2+ 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_%{major_ver}.orig.tar.gz +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 -Source4: 56atd -Source5: atd.systemd - -Patch1: at-3.1.12-makefile.patch -Patch2: at-3.1.12-opt_V.patch -Patch3: at-3.1.12-shell.patch -Patch4: at-3.1.12-nitpicks.patch -Patch5: at-3.1.12-pam.patch -Patch6: at-3.1.12-selinux.patch -Patch7: at-3.1.12-fix.patch -Patch8: at-3.1.12-nowrap.patch -Patch9: at-3.1.12-fix_no_export.patch +Source1: pam_atd +Source2: atd.init +Source3: atd.sysconf +Source4: 56atd +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 BuildRequires: fileutils /etc/init.d BuildRequires: flex flex-static bison autoconf @@ -75,9 +71,8 @@ cp %{SOURCE1} . %patch4 -p1 -b .nit %patch5 -p1 -b .pam %patch6 -p1 -b .selinux -%patch7 -p1 -b .fix -%patch8 -p1 -b .nowrap -%patch9 -p1 -b .export +%patch7 -p1 -b .nowrap +%patch8 -p1 -b .export %build # patch9 touches configure.in @@ -122,10 +117,6 @@ 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 -mv -f %{buildroot}/%{_mandir}/man5/at_allow.5 \ - %{buildroot}/%{_mandir}/man5/at.allow.5 -rm -f %{buildroot}/%{_mandir}/man5/at_deny.5 - mkdir -p %{buildroot}/etc/sysconfig install -m 644 %{SOURCE3} %{buildroot}/etc/sysconfig/atd @@ -197,6 +188,10 @@ fi %attr(0755,root,root) %{_initrddir}/atd %changelog +* Fri Jul 29 2011 Marcela Mašláňová - 3.1.13-1 +- update to 3.1.13 +- rewrite patches to be applicable + * Thu Jul 21 2011 Marcela Mašláňová - 3.1.12-11 - fix permission of init.d/atd diff --git a/test.pl b/test.pl deleted file mode 100755 index 4bdba6c..0000000 --- a/test.pl +++ /dev/null @@ -1,800 +0,0 @@ -#!/usr/bin/perl -w -# -# test.pl - tests validity of lexer/parser for at(1) -# -# Copyright 2001 David D. Kilzer -# -# Licensed under the GNU Public License -# -# Environment variables: -# TEST_VERBOSE -# 0 - no verbosity -# 1 - verbose output only on failed tests, and all stderr output -# > 1 - verbose output on every test, and all stderr output -# - -use strict; - -use constant SECOND => 1; # seconds per second -use constant MINUTE => 60*SECOND; # seconds per minute -use constant HOUR => 60*MINUTE; # seconds per hour -use constant DAY => 24*HOUR; # seconds per day -use constant WEEK => 7*DAY; # seconds per week - -use vars qw($verbose); - -use POSIX; # strftime -use Time::Local; # timelocal() and timegm() - -BEGIN { $| = 1; } # no output buffering - - -# -# Subroutines -# -sub is_dst (;$); # is time in DST? -sub get_utc_offset (;$); # calculate hours offset from UTC - - -# -# Data structures containing test data -# -my @date_tests; # date strings -my @time_tests; # time strings -my @date_time_tests_time; # time + date strings (just times) -my @date_time_tests_date; # time + date strings (just dates) -my @inc_dec_tests; # increment and decrement strings -my @misc_tests; # miscellaneous strings (mostly for DST) - -my $num_tests; # number of tests -my $show_stderr; # set to "2> /dev/null" if (! $verbose) -my $utc_off; # timezone offset in minutes west of UTC - - -# -# Set variables before running tests -# -$verbose = $ENV{'TEST_VERBOSE'} || 0; - -$show_stderr = ($verbose > 0 ? "" : "2> /dev/null"); - -$utc_off = get_utc_offset(); - - -# -# Tests for dates only -# These tests include both relative and specific dates. -# They are not combined with any other tests. -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@date_tests = -( -[ "dec 31", 12, 31, '$y', '$h', '$mi' ], -[ "Dec 31", 12, 31, '$y', '$h', '$mi' ], -[ "DEC 31", 12, 31, '$y', '$h', '$mi' ], -[ "december 31", 12, 31, '$y', '$h', '$mi' ], -[ "December 31", 12, 31, '$y', '$h', '$mi' ], -[ "DECEMBER 31", 12, 31, '$y', '$h', '$mi' ], -[ "Dec 31 10", 12, 31, 2010, '$h', '$mi' ], -[ "December 31 10", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31 2010", 12, 31, 2010, '$h', '$mi' ], -[ "December 31 2010", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31,10", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31, 10", 12, 31, 2010, '$h', '$mi' ], -[ "December 31,10", 12, 31, 2010, '$h', '$mi' ], -[ "December 31, 10", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31,2010", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31, 2010", 12, 31, 2010, '$h', '$mi' ], -[ "December 31,2010", 12, 31, 2010, '$h', '$mi' ], -[ "December 31, 2010", 12, 31, 2010, '$h', '$mi' ], -[ "sun", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "Sun", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "SUN", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "sunday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "Sunday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "SUNDAY", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 0 ? 7 : ((7 - $wd + 0) % 7)) * DAY)' ], -[ "Mon", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 1 ? 7 : ((7 - $wd + 1) % 7)) * DAY)' ], -[ "Monday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 1 ? 7 : ((7 - $wd + 1) % 7)) * DAY)' ], -[ "Tue", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 2 ? 7 : ((7 - $wd + 2) % 7)) * DAY)' ], -[ "Tuesday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 2 ? 7 : ((7 - $wd + 2) % 7)) * DAY)' ], -[ "Wed", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 3 ? 7 : ((7 - $wd + 3) % 7)) * DAY)' ], -[ "Wednesday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 3 ? 7 : ((7 - $wd + 3) % 7)) * DAY)' ], -[ "Thu", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 4 ? 7 : ((7 - $wd + 4) % 7)) * DAY)' ], -[ "Thursday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 4 ? 7 : ((7 - $wd + 4) % 7)) * DAY)' ], -[ "Fri", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 5 ? 7 : ((7 - $wd + 5) % 7)) * DAY)' ], -[ "Friday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 5 ? 7 : ((7 - $wd + 5) % 7)) * DAY)' ], -[ "Sat", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 6 ? 7 : ((7 - $wd + 6) % 7)) * DAY)' ], -[ "Saturday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 6 ? 7 : ((7 - $wd + 6) % 7)) * DAY)' ], -[ "now", '$mo', '$d', '$y', '$h', '$mi' ], -[ "Now", '$mo', '$d', '$y', '$h', '$mi' ], -[ "NOW", '$mo', '$d', '$y', '$h', '$mi' ], -[ "today", '$mo', '$d', '$y', '$h', '$mi' ], -[ "Today", '$mo', '$d', '$y', '$h', '$mi' ], -[ "TODAY", '$mo', '$d', '$y', '$h', '$mi' ], -[ "tomorrow", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "Tomorrow", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "TOMORROW", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "10-12-31", 12, 31, 2010, '$h', '$mi' ], -[ "2010-12-31", 12, 31, 2010, '$h', '$mi' ], -[ "31.12.10", 12, 31, 2010, '$h', '$mi' ], -[ "31.12.2010", 12, 31, 2010, '$h', '$mi' ], -[ "31 Dec", 12, 31, '$y', '$h', '$mi' ], -[ "31 December", 12, 31, '$y', '$h', '$mi' ], -[ "31 Dec 10", 12, 31, 2010, '$h', '$mi' ], -[ "31 Dec 2010", 12, 31, 2010, '$h', '$mi' ], -[ "31 December 10", 12, 31, 2010, '$h', '$mi' ], -[ "31 December 2010", 12, 31, 2010, '$h', '$mi' ], -[ "12/31/10", 12, 31, 2010, '$h', '$mi' ], -[ "12/31/2010", 12, 31, 2010, '$h', '$mi' ], -[ "13010", 01, 30, 2010, '$h', '$mi' ], -[ "1302010", 01, 30, 2010, '$h', '$mi' ], -[ "013010", 01, 30, 2010, '$h', '$mi' ], -[ "01302010", 01, 30, 2010, '$h', '$mi' ], -[ "123110", 12, 31, 2010, '$h', '$mi' ], -[ "12312010", 12, 31, 2010, '$h', '$mi' ], -[ "next minute", '$mo', '$d', '$y', '$h', '$mi', '1 * MINUTE' ], -[ "next hour", '$mo', '$d', '$y', '$h', '$mi', '1 * HOUR' ], -[ "next day", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "next week", '$mo', '$d', '$y', '$h', '$mi', '1 * WEEK' ], -[ "next month", '($mo == 12 ? 1 : $mo + 1)', '$d', '($mo == 12 ? $y + 1 : $y)', '$h', '$mi' ], -[ "next year", '$mo', '$d', '$y + 1', '$h', '$mi' ], -); - - -# -# Tests for times only -# These tests include specific times and time aliases. -# They are not combined with any other tests. -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@time_tests = -( -[ "0800", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "2300", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8:00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08:00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "23:00", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8'00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08'00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "23'00", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8.00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08.00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "23.00", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8h00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08h00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "23h00", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8,00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08,00", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "23,00", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8:00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08:00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "11:00 pm", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8'00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08'00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "11'00 pm", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8.00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08.00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "11.00 pm", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8h00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08h00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "11h00 pm", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "8,00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "08,00 am", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi) < ( 8*60+0) ? 0 : 1 * DAY)' ], -[ "11,00 pm", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi) < (23*60+0) ? 0 : 1 * DAY)' ], -[ "0800 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "2300 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8:00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08:00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "23:00 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8'00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08'00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "23'00 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8.00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08.00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "23.00 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8h00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08h00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "23h00 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8,00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08,00 utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "23,00 utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8:00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08:00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "11:00 pm utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8'00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08'00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "11'00 pm utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8.00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08.00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "11.00 pm utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8h00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08h00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "11h00 pm utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "8,00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "08,00 am utc", '$mo', '$d', '$y', 8, 0, - '(($h*60+$mi+$utc_off) < ( 8*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "11,00 pm utc", '$mo', '$d', '$y', 23, 0, - '(($h*60+$mi+$utc_off) < (23*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "noon", '$mo', '$d', '$y', 12, 0, - '(($h*60+$mi) < (12*60+0) ? 0 : 1 * DAY)' ], -[ "Noon", '$mo', '$d', '$y', 12, 0, - '(($h*60+$mi) < (12*60+0) ? 0 : 1 * DAY)' ], -[ "NOON", '$mo', '$d', '$y', 12, 0, - '(($h*60+$mi) < (12*60+0) ? 0 : 1 * DAY)' ], -[ "midnight", '$mo', '$d', '$y', 0, 0, - '(($h*60+$mi) < ( 0*60+0) ? 1 * DAY : 1 * DAY)' ], -[ "teatime", '$mo', '$d', '$y', 16, 0, - '(($h*60+$mi) < (16*60+0) ? 0 : 1 * DAY)' ], -[ "noon utc", '$mo', '$d', '$y', 12, 0, - '(($h*60+$mi+$utc_off) < (12*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "noon UTC", '$mo', '$d', '$y', 12, 0, - '(($h*60+$mi+$utc_off) < (12*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -[ "midnight utc", '$mo', '$d', '$y', 0, 0, - '(($h*60+$mi+$utc_off) < ( 0*60+0) ? 1 * DAY : 1 * DAY) - $utc_off * MINUTE' ], -[ "teatime utc", '$mo', '$d', '$y', 16, 0, - '(($h*60+$mi+$utc_off) < (16*60+0) ? 0 : 1 * DAY) - $utc_off * MINUTE' ], -); - - -# -# Tests for combining times and dates and inc/dec -# These tests include specific times and time aliases that are -# combined with @date_time_tests_date and with @inc_dec_tests -# during testing. -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@date_time_tests_time = -( -[ "0800", '$mo', '$d', '$y', 8, 0 ], -[ "2300", '$mo', '$d', '$y', 23, 0 ], -[ "8:00", '$mo', '$d', '$y', 8, 0 ], -[ "23:00", '$mo', '$d', '$y', 23, 0 ], -[ "8'00", '$mo', '$d', '$y', 8, 0 ], -[ "23'00", '$mo', '$d', '$y', 23, 0 ], -[ "8.00", '$mo', '$d', '$y', 8, 0 ], -[ "23.00", '$mo', '$d', '$y', 23, 0 ], -[ "8h00", '$mo', '$d', '$y', 8, 0 ], -[ "23h00", '$mo', '$d', '$y', 23, 0 ], -[ "8,00", '$mo', '$d', '$y', 8, 0 ], -[ "23,00", '$mo', '$d', '$y', 23, 0 ], -[ "8:00 am", '$mo', '$d', '$y', 8, 0 ], -[ "11:00 pm", '$mo', '$d', '$y', 23, 0 ], -[ "8'00 am", '$mo', '$d', '$y', 8, 0 ], -[ "11'00 pm", '$mo', '$d', '$y', 23, 0 ], -[ "8.00 am", '$mo', '$d', '$y', 8, 0 ], -[ "11.00 pm", '$mo', '$d', '$y', 23, 0 ], -[ "8h00 am", '$mo', '$d', '$y', 8, 0 ], -[ "11h00 pm", '$mo', '$d', '$y', 23, 0 ], -[ "8,00 am", '$mo', '$d', '$y', 8, 0 ], -[ "11,00 pm", '$mo', '$d', '$y', 23, 0 ], -[ "0800 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "2300 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8:00 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "23:00 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8'00 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "23'00 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8.00 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "23.00 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8h00 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "23h00 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8,00 utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "23,00 utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8:00 am utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "11:00 pm utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8'00 am utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "11'00 pm utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8.00 am utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "11.00 pm utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8h00 am utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "11h00 pm utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "8,00 am utc", '$mo', '$d', '$y', 8, 0, - '- $utc_off * MINUTE' ], -[ "11,00 pm utc", '$mo', '$d', '$y', 23, 0, - '- $utc_off * MINUTE' ], -[ "noon", '$mo', '$d', '$y', 12, 0 ], -[ "midnight", '$mo', '$d', '$y', 0, 0 ], -[ "teatime", '$mo', '$d', '$y', 16, 0 ], -[ "noon utc", '$mo', '$d', '$y', 12, 0, - '- $utc_off * MINUTE' ], -[ "midnight utc", '$mo', '$d', '$y', 0, 0, - '- $utc_off * MINUTE' ], -[ "teatime utc", '$mo', '$d', '$y', 16, 0, - '- $utc_off * MINUTE' ], -); - - -# -# Tests for combining times and dates and inc/dec -# These tests include both relative and specific dates that are -# combined with @date_time_tests_time and with @inc_dec_tests -# during testing. -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@date_time_tests_date = -( -[ "Dec 31", 12, 31, '$y', '$h', '$mi' ], -[ "Dec 31 10", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31 2010", 12, 31, 2010, '$h', '$mi' ], -[ "Dec 31, 10", 12, 31, 2010, '$h', '$mi' ], -[ "December 31, 2010", 12, 31, 2010, '$h', '$mi' ], -[ "Monday", '$mo', '$d', '$y', '$h', '$mi', - '(($wd == 1 ? 7 : ((7 - $wd + 1) % 7)) * DAY)' ], -[ "today", '$mo', '$d', '$y', '$h', '$mi' ], -[ "tomorrow", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "10-12-31", 12, 31, 2010, '$h', '$mi' ], -[ "2010-12-31", 12, 31, 2010, '$h', '$mi' ], -[ "31.12.10", 12, 31, 2010, '$h', '$mi' ], -[ "31.12.2010", 12, 31, 2010, '$h', '$mi' ], -[ "31 Dec", 12, 31, '$y', '$h', '$mi' ], -[ "31 Dec 10", 12, 31, 2010, '$h', '$mi' ], -[ "31 Dec 2010", 12, 31, 2010, '$h', '$mi' ], -[ "12/31/10", 12, 31, 2010, '$h', '$mi' ], -[ "12/31/2010", 12, 31, 2010, '$h', '$mi' ], -[ "13010", 01, 30, 2010, '$h', '$mi' ], -[ "1302010", 01, 30, 2010, '$h', '$mi' ], -[ "123110", 12, 31, 2010, '$h', '$mi' ], -[ "12312010", 12, 31, 2010, '$h', '$mi' ], -[ "next minute", '$mo', '$d', '$y', '$h', '$mi', '1 * MINUTE' ], -[ "next hour", '$mo', '$d', '$y', '$h', '$mi', '1 * HOUR' ], -[ "next day", '$mo', '$d', '$y', '$h', '$mi', '1 * DAY' ], -[ "next week", '$mo', '$d', '$y', '$h', '$mi', '1 * WEEK' ], -[ "next month", '($mo == 12 ? 1 : $mo + 1)', '$d', '($mo == 12 ? $y + 1 : $y)', '$h', '$mi' ], -[ "next year", '$mo', '$d', '$y + 1', '$h', '$mi' ], -); - - -# -# Tests for combining times and dates and inc/dec -# These tests include both increments and decrements that are -# combined with @date_time_tests_time and with @date_time_tests_date -# during testing. Note how these tests refer to elements from -# the data structures that they will be combined with ($$i[N]). -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@inc_dec_tests = -( -[ "- 1 min", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 1 * MINUTE' ], -[ "- 1 minute", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 1 * MINUTE' ], -[ "- 1 hour", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 1 * HOUR' ], -[ "- 1 day", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 1 * DAY' ], -[ "- 1 week", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 1 * WEEK' ], -[ "- 1 month", '($$i[1] == 1 ? 12 : $$i[1] - 1)', '$$i[2]', '($$i[1] == 1 ? $$i[3] - 1 : $$i[3])', '$$i[4]', '$$i[5]' ], -[ "- 1 year", '$$i[1]', '$$i[2]', '$$i[3] - 1', '$$i[4]', '$$i[5]' ], -[ "- 10 min", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 10 * MINUTE' ], -[ "- 10 minutes", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 10 * MINUTE' ], -[ "- 10 hours", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 10 * HOUR' ], -[ "- 10 days", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 10 * DAY' ], -[ "- 10 weeks", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '- 10 * WEEK' ], -[ "- 10 months", '($$i[1] > 10 ? $$i[1] - 10 : $$i[1] + 2)', '$$i[2]', '($$i[1] > 10 ? $$i[3]: $$i[3] - 1)', '$$i[4]', '$$i[5]' ], -[ "- 10 years", '$$i[1]', '$$i[2]', '$$i[3] - 10', '$$i[4]', '$$i[5]' ], -[ "+ 1 min", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 1 * MINUTE' ], -[ "+ 1 minute", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 1 * MINUTE' ], -[ "+ 1 hour", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 1 * HOUR' ], -[ "+ 1 day", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 1 * DAY' ], -[ "+ 1 week", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 1 * WEEK' ], -[ "+ 1 month", '($$i[1] == 12 ? 1 : $$i[1] + 1)', '$$i[2]', '($$i[1] == 12 ? $$i[3] + 1 : $$i[3])', '$$i[4]', '$$i[5]' ], -[ "+ 1 year", '$$i[1]', '$$i[2]', '$$i[3] + 1', '$$i[4]', '$$i[5]' ], -[ "+ 10 min", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 10 * MINUTE' ], -[ "+ 10 minutes", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 10 * MINUTE' ], -[ "+ 10 hours", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 10 * HOUR' ], -[ "+ 10 days", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 10 * DAY' ], -[ "+ 10 weeks", '$$i[1]', '$$i[2]', '$$i[3]', '$$i[4]', '$$i[5]', '+ 10 * WEEK' ], -[ "+ 10 months", '($$i[1] < 3 ? $$i[1] + 10 : $$i[1] - 2)', '$$i[2]', '($$i[1] < 3 ? $$i[3] : $$i[3] + 1)', '$$i[4]', '$$i[5]' ], -[ "+ 10 years", '$$i[1]', '$$i[2]', '$$i[3] + 10', '$$i[4]', '$$i[5]' ], -); - - -# -# Miscellaneous tests -# These tests include any specific test cases that won't fit easily -# into the test data above. -# They are not combined with any other tests. -# -# Format: "string", month, day, year, hour, minute, [offset] -# -@misc_tests = -( -# Test moving back and forth across DST -[ "March 1 + 3 months", '6', '1', '$y', '$h', '$mi' ], -[ "June 1 - 3 months", '3', '1', '$y', '$h', '$mi' ], -[ "September 1 + 3 months", '12', '1', '$y', '$h', '$mi' ], -[ "December 1 - 3 months", '9', '1', '$y', '$h', '$mi' ], -[ "March 1 + 12 weeks", '3', '1', '$y', '$h', '$mi', '+12 * WEEK' ], -[ "June 1 - 12 weeks", '6', '1', '$y', '$h', '$mi', '-12 * WEEK' ], -[ "September 1 + 12 weeks", '9', '1', '$y', '$h', '$mi', '+12 * WEEK' ], -[ "December 1 - 12 weeks", '12', '1', '$y', '$h', '$mi', '-12 * WEEK' ], -); - - -$num_tests = ($#date_tests + 1) - + ($#time_tests + 1) - + ($#misc_tests + 1) - + ($#date_time_tests_time + 1) * ($#date_time_tests_date + 1) - + ($#date_time_tests_time + 1) * ($#inc_dec_tests + 1) - + ($#date_time_tests_date + 1) * ($#inc_dec_tests + 1) - ; - - -# -# Print out the number of tests to perform -# -print "1..$num_tests\n"; - - -# -# Run date, time and miscellaneous tests -# -foreach my $i (@date_tests, @time_tests, @misc_tests) -{ - my $s; # current second - my $mi; # current minute - my $h; # current hour - my $d; # current day - my $mo; # current month - my $y; # current year - my $wd; # current week day - my $yd; # current year day - my $dst; # is daylight savings time? - - my $epoch_time; # time string in epoch seconds - my $offset = 0; # offset for test in epoch seconds - my $t; # time string to test against - - my $o; # output of parsetest command - my $run_time; # internal timestamp used for comparison - - ## WARNING: Next two statements could run in different minutes! - $o = `./parsetest \"$$i[0]\" $show_stderr`; - $run_time = time(); - - ## Set variables for $run_time before calculating $offset - ($s, $mi, $h, $d, $mo, $y, $wd, $yd, $dst) = localtime($run_time); - $mo += 1; - $y += 1900; - - $offset = eval "$$i[6]" if (defined $$i[6]); - - $epoch_time = strftime("%s", - 0, - eval "$$i[5]", - eval "$$i[4]", - eval "$$i[2]", - eval "$$i[1] - 1", - eval "$$i[3] - 1900", - -1, # wday - -1, # yday - -1, # isdst - ); - - ## Adjust +-1 hour when moving in or out of DST - if ( is_dst($epoch_time) && ! is_dst($epoch_time + $offset)) - { # DST to no DST - $epoch_time += 1 * HOUR; - } - elsif (! is_dst($epoch_time) && is_dst($epoch_time + $offset)) - { # no DST to DST - $epoch_time -= 1 * HOUR; - } - - $t = strftime("%a %b %e %H:%M:00 %Y", localtime($epoch_time + $offset)); - - chomp $o; - - print $o eq $t ? "ok" : "not ok", "\n"; - - print "'", $$i[0], "': '$o' =? '$t'\n" - if ($verbose > 1 || ($verbose == 1 && $o ne $t)); -} - - -# -# Run time + date tests -# -foreach my $i (@date_time_tests_time) -{ - foreach my $j (@date_time_tests_date) - { - my $s; # current second - my $mi; # current minute - my $h; # current hour - my $d; # current day - my $mo; # current month - my $y; # current year - my $wd; # current week day - my $yd; # current year day - my $dst; # is daylight savings time? - - my $epoch_time; # time string in epoch seconds - my $offset = 0; # offset for test in epoch seconds - my $t; # time string to test against - - my $o; # output of parsetest command - my $run_time; # internal timestamp used for comparison - - ## WARNING: Next two statements could run in different minutes! - $o = `./parsetest \"$$i[0] $$j[0]\" $show_stderr`; - $run_time = time(); - - ## Set variables for $run_time before calculating $offset - ($s, $mi, $h, $d, $mo, $y, $wd, $yd, $dst) = localtime($run_time); - $mo += 1; - $y += 1900; - - if (defined $$i[6]) - { - if (defined $$j[6]) - { - $offset = eval "($$i[6]) + ($$j[6])"; - } - else - { - $offset = eval "$$i[6]"; - } - } - elsif (defined $$j[6]) - { - $offset = eval "$$j[6]"; - } - - $epoch_time = strftime("%s", - 0, - eval "$$i[5]", - eval "$$i[4]", - eval "$$j[2]", - eval "$$j[1] - 1", - eval "$$j[3] - 1900", - -1, # wday - -1, # yday - -1, # isdst - ); - - ## Adjust +-1 hour when moving in or out of DST - if ( is_dst($epoch_time) && ! is_dst($epoch_time + $offset)) - { # DST to no DST - $epoch_time += 1 * HOUR; - } - elsif (! is_dst($epoch_time) && is_dst($epoch_time + $offset)) - { # no DST to DST - $epoch_time -= 1 * HOUR; - } - - $t = strftime("%a %b %e %H:%M:00 %Y", localtime($epoch_time + $offset)); - - chomp $o; - - print $o eq $t ? "ok" : "not ok", "\n"; - - print "'$$i[0] $$j[0]': '$o' =? '$t'\n" - if ($verbose > 1 || ($verbose == 1 && $o ne $t)); - } -} - - -# -# Run time + inc_dec and date + inc_dec tests -# -foreach my $i (@date_time_tests_time, @date_time_tests_date) -{ - foreach my $j (@inc_dec_tests) - { - my $s; # current second - my $mi; # current minute - my $h; # current hour - my $d; # current day - my $mo; # current month - my $y; # current year - my $wd; # current week day - my $yd; # current year day - my $dst; # is daylight savings time? - - my $epoch_time; # time string in epoch seconds - my $offset = 0; # offset for test in epoch seconds - my $t; # time string to test against - - my $o; # output of parsetest command - my $run_time; # internal timestamp used for comparison - - ## WARNING: Next two statements could run in different minutes! - $o = `./parsetest \"$$i[0] $$j[0]\" $show_stderr`; - $run_time = time(); - - ## Set variables for $run_time before calculating $offset - ($s, $mi, $h, $d, $mo, $y, $wd, $yd, $dst) = localtime($run_time); - $mo += 1; - $y += 1900; - - if (defined $$i[6]) - { - if (defined $$j[6]) - { - $offset = eval "($$i[6]) + ($$j[6])"; - } - else - { - $offset = eval "$$i[6]"; - } - } - elsif (defined $$j[6]) - { - $offset = eval "$$j[6]"; - } - - $epoch_time = strftime("%s", - 0, - eval "$$i[5]", - eval "$$i[4]", - eval "eval \"$$j[2]\"", - eval "eval \"$$j[1] - 1\"", - eval "eval \"$$j[3] - 1900\"", - -1, # wday - -1, # yday - -1, # isdst - ); - - ## Adjust +-1 hour when moving in or out of DST - if ( is_dst($epoch_time) && ! is_dst($epoch_time + $offset)) - { # DST to no DST - $epoch_time += 1 * HOUR; - } - elsif (! is_dst($epoch_time) && is_dst($epoch_time + $offset)) - { # no DST to DST - $epoch_time -= 1 * HOUR; - } - - $t = strftime("%a %b %e %H:%M:00 %Y", localtime($epoch_time + $offset)); - - chomp $o; - - print $o eq $t ? "ok" : "not ok", "\n"; - - print "'$$i[0] $$j[0]': '$o' =? '$t'\n" - if ($verbose > 1 || ($verbose == 1 && $o ne $t)); - } -} - -exit 0; - - -# -# Subroutine: -# is_dst -# -# Description: -# returns true if the time passed in is in DST, else -# returns false if the time passed in is not in DST -# -# Arg 1: -# [Optional] time in epoch seconds; defaults to the current -# time if no argument is given -# -sub is_dst (;$) -{ - my $t = shift || time(); - return ((localtime($t))[8] > 0); -} - - -# -# Subroutine: -# get_utc_offset -# -# Description: -# returns the number of offest hours from UTC for the current timezone -# -# Arg 1: -# [Optional] time in epoch seconds; defaults to the current -# time if no argument is given -# -sub get_utc_offset (;$) -{ - my $t = shift || time(); - my @t = localtime($t); - my $is_dst = $t[8]; - return ((timelocal(@t) - timegm(@t) + ($is_dst > 0 ? HOUR : 0)) / MINUTE); -} -