This also gets rid of set_cron_cwd(), cron now chdirs to '/' via
daemon(3).  We can assume that the cron/at dirs were created at
install time and we can't actually create them with the correct
mode or group due to pledge anyway.

I've moved the setegid(crontab) bit to open_socket() where it is
actually needed.  Now that common.c is gone I've moved strtot()
into at.c and atrun.c (it was not actually common).

 - todd

Index: usr.sbin/cron/Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/cron/Makefile,v
retrieving revision 1.5
diff -u -p -u -r1.5 Makefile
--- usr.sbin/cron/Makefile      31 Oct 2015 12:19:41 -0000      1.5
+++ usr.sbin/cron/Makefile      12 Nov 2015 16:17:47 -0000
@@ -2,7 +2,7 @@
 
 PROG=  cron
 SRCS=  cron.c database.c user.c entry.c job.c do_command.c \
-       misc.c env.c popen.c atrun.c common.c
+       misc.c env.c popen.c atrun.c
 CFLAGS+=-I${.CURDIR}
 MAN=   cron.8
 
Index: usr.sbin/cron/atrun.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/atrun.c,v
retrieving revision 1.38
diff -u -p -u -r1.38 atrun.c
--- usr.sbin/cron/atrun.c       9 Nov 2015 16:37:07 -0000       1.38
+++ usr.sbin/cron/atrun.c       12 Nov 2015 16:17:47 -0000
@@ -50,6 +50,21 @@
 
 static void run_job(atjob *, char *);
 
+static int
+strtot(const char *nptr, char **endptr, time_t *tp)
+{
+       long long ll;
+
+       errno = 0;
+       ll = strtoll(nptr, endptr, 10);
+       if (*endptr == nptr)
+               return (-1);
+       if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll)
+               return (-1);
+       *tp = (time_t)ll;
+       return (0);
+}
+
 /*
  * Scan the at jobs dir and build up a list of jobs found.
  */
@@ -65,12 +80,12 @@ scan_atjobs(at_db **db, struct timespec 
        struct dirent *file;
        struct stat sb;
 
-       if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) {
-               log_it("CRON", "OPEN FAILED", AT_SPOOL);
+       if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) {
+               log_it("CRON", "OPEN FAILED", _PATH_AT_SPOOL);
                return (0);
        }
        if (fstat(dfd, &sb) != 0) {
-               log_it("CRON", "FSTAT FAILED", AT_SPOOL);
+               log_it("CRON", "FSTAT FAILED", _PATH_AT_SPOOL);
                close(dfd);
                return (0);
        }
@@ -80,7 +95,7 @@ scan_atjobs(at_db **db, struct timespec 
        }
 
        if ((atdir = fdopendir(dfd)) == NULL) {
-               log_it("CRON", "OPENDIR FAILED", AT_SPOOL);
+               log_it("CRON", "OPENDIR FAILED", _PATH_AT_SPOOL);
                close(dfd);
                return (0);
        }
@@ -148,7 +163,7 @@ scan_atjobs(at_db **db, struct timespec 
 void
 atrun(at_db *db, double batch_maxload, time_t now)
 {
-       char atfile[MAX_FNAME];
+       char atfile[PATH_MAX];
        struct stat sb;
        double la;
        atjob *job, *tjob, *batch = NULL;
@@ -161,7 +176,7 @@ atrun(at_db *db, double batch_maxload, t
                if (job->run_time > now)
                        continue;
 
-               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL,
+               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
                    (long long)job->run_time, job->queue);
 
                if (lstat(atfile, &sb) != 0 || !S_ISREG(sb.st_mode)) {
@@ -194,7 +209,7 @@ atrun(at_db *db, double batch_maxload, t
            && (batch_maxload == 0.0 ||
            ((getloadavg(&la, 1) == 1) && la <= batch_maxload))
            ) {
-               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL,
+               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
                    (long long)batch->run_time, batch->queue);
                run_job(batch, atfile);
                TAILQ_REMOVE(&db->jobs, batch, entries);
@@ -420,8 +435,6 @@ run_job(atjob *job, char *atfile)
                        login_close(lc);
                }
 
-               chdir("/");             /* at job will chdir to correct place */
-
                /* If this is a low priority job, nice ourself. */
                if (job->queue > 'b')
                        (void)setpriority(PRIO_PROCESS, 0, job->queue - 'b');
@@ -480,8 +493,8 @@ run_job(atjob *job, char *atfile)
                fprintf(mail, "To: %s\n", mailto);
                fprintf(mail, "Subject: Output from \"at\" job\n");
                fprintf(mail, "Auto-Submitted: auto-generated\n");
-               fprintf(mail, "\nYour \"at\" job on %s\n\"%s/%s/%s\"\n",
-                   hostname, CRONDIR, AT_SPOOL, atfile);
+               fprintf(mail, "\nYour \"at\" job on %s\n\"%s/%s\"\n",
+                   hostname, _PATH_AT_SPOOL, atfile);
                fprintf(mail, "\nproduced the following output:\n\n");
 
                /* Pipe the job's output to sendmail. */
Index: usr.sbin/cron/client.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/client.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 client.c
--- usr.sbin/cron/client.c      12 Nov 2015 13:42:42 -0000      1.7
+++ usr.sbin/cron/client.c      12 Nov 2015 16:17:47 -0000
@@ -88,19 +88,19 @@ allowed(const char *username, const char
        return (isallowed);
 }
 
-/* void poke_daemon(const char *spool_dir, unsigned char cookie)
+/* void poke_daemon(unsigned char cookie)
  *     touches spool_dir and sends a poke to the cron daemon if running.
  */
 void
-poke_daemon(const char *spool_dir, unsigned char cookie)
+poke_daemon(unsigned char cookie)
 {
        int sock = -1;
-       const char *cronsock = CRONSOCK;
+       const char *cronsock = _PATH_CRON_SOCK;
        struct stat sb;
        struct sockaddr_un s_un;
 
        if (stat(cronsock, &sb) != 0)
-               cronsock = CRONSOCK_OLD;        /* backwards compatibility */
+               cronsock = _PATH_CRON_SOCK_OLD; /* backwards compatibility */
 
        bzero(&s_un, sizeof(s_un));
        if (strlcpy(s_un.sun_path, cronsock, sizeof(s_un.sun_path)) >=
Index: usr.sbin/cron/common.c
===================================================================
RCS file: usr.sbin/cron/common.c
diff -N usr.sbin/cron/common.c
--- usr.sbin/cron/common.c      12 Nov 2015 13:42:42 -0000      1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,136 +0,0 @@
-/*     $OpenBSD: common.c,v 1.5 2015/11/12 13:42:42 millert Exp $      */
-
-/* Copyright 1988,1990,1993,1994 by Paul Vixie
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>         /* for structs.h */
-#include <errno.h>
-#include <grp.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "pathnames.h"
-#include "macros.h"
-#include "structs.h"
-#include "funcs.h"
-#include "globals.h"
-
-void
-set_cron_cwd(void)
-{
-       struct stat sb;
-       struct group *grp = NULL;
-
-       grp = getgrnam(CRON_GROUP);
-       /* first check for CRONDIR ("/var/cron" or some such)
-        */
-       if (stat(CRONDIR, &sb) < 0 && errno == ENOENT) {
-               perror(CRONDIR);
-               if (0 == mkdir(CRONDIR, 0710)) {
-                       fprintf(stderr, "%s: created\n", CRONDIR);
-                       stat(CRONDIR, &sb);
-               } else {
-                       fprintf(stderr, "%s: ", CRONDIR);
-                       perror("mkdir");
-                       exit(EXIT_FAILURE);
-               }
-       }
-       if (!S_ISDIR(sb.st_mode)) {
-               fprintf(stderr, "'%s' is not a directory, bailing out.\n",
-                       CRONDIR);
-               exit(EXIT_FAILURE);
-       }
-       if (chdir(CRONDIR) < 0) {
-               fprintf(stderr, "cannot chdir(%s), bailing out.\n", CRONDIR);
-               perror(CRONDIR);
-               exit(EXIT_FAILURE);
-       }
-
-       /* CRONDIR okay (now==CWD), now look at CRON_SPOOL ("tabs" or some such)
-        */
-       if (stat(CRON_SPOOL, &sb) < 0 && errno == ENOENT) {
-               perror(CRON_SPOOL);
-               if (0 == mkdir(CRON_SPOOL, 0700)) {
-                       fprintf(stderr, "%s: created\n", CRON_SPOOL);
-                       stat(CRON_SPOOL, &sb);
-               } else {
-                       fprintf(stderr, "%s: ", CRON_SPOOL);
-                       perror("mkdir");
-                       exit(EXIT_FAILURE);
-               }
-       }
-       if (!S_ISDIR(sb.st_mode)) {
-               fprintf(stderr, "'%s' is not a directory, bailing out.\n",
-                       CRON_SPOOL);
-               exit(EXIT_FAILURE);
-       }
-       if (grp != NULL) {
-               if (sb.st_gid != grp->gr_gid)
-                       chown(CRON_SPOOL, -1, grp->gr_gid);
-               if ((sb.st_mode & ALLPERMS) != 01730)
-                       chmod(CRON_SPOOL, 01730);
-       }
-
-       /* finally, look at AT_SPOOL ("atjobs" or some such)
-        */
-       if (stat(AT_SPOOL, &sb) < 0 && errno == ENOENT) {
-               perror(AT_SPOOL);
-               if (0 == mkdir(AT_SPOOL, 0700)) {
-                       fprintf(stderr, "%s: created\n", AT_SPOOL);
-                       stat(AT_SPOOL, &sb);
-               } else {
-                       fprintf(stderr, "%s: ", AT_SPOOL);
-                       perror("mkdir");
-                       exit(EXIT_FAILURE);
-               }
-       }
-       if (!S_ISDIR(sb.st_mode)) {
-               fprintf(stderr, "'%s' is not a directory, bailing out.\n",
-                       AT_SPOOL);
-               exit(EXIT_FAILURE);
-       }
-       if (grp != NULL) {
-               setegid(grp->gr_gid);
-               if (sb.st_gid != grp->gr_gid)
-                       chown(AT_SPOOL, -1, grp->gr_gid);
-               if ((sb.st_mode & ALLPERMS) != 01770)
-                       chmod(AT_SPOOL, 01770);
-       }
-}
-
-int
-strtot(const char *nptr, char **endptr, time_t *tp)
-{
-       long long ll;
-
-       errno = 0;
-       ll = strtoll(nptr, endptr, 10);
-       if (*endptr == nptr)
-               return (-1);
-       if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll)
-               return (-1);
-       *tp = (time_t)ll;
-       return (0);
-}
Index: usr.sbin/cron/cron.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/cron.c,v
retrieving revision 1.69
diff -u -p -u -r1.69 cron.c
--- usr.sbin/cron/cron.c        12 Nov 2015 13:42:42 -0000      1.69
+++ usr.sbin/cron/cron.c        12 Nov 2015 16:17:47 -0000
@@ -25,6 +25,7 @@
 
 #include <bitstring.h>
 #include <errno.h>
+#include <grp.h>
 #include <locale.h>
 #include <poll.h>
 #include <signal.h>
@@ -97,8 +98,6 @@ main(int argc, char *argv[])
        sact.sa_handler = SIG_IGN;
        (void) sigaction(SIGPIPE, &sact, NULL);
 
-       set_cron_cwd();
-
        if (pledge("stdio rpath wpath cpath fattr getpw unix id dns proc exec",
            NULL) == -1) {
                log_it("CRON", "pledge", strerror(errno));
@@ -113,7 +112,7 @@ main(int argc, char *argv[])
        }
 
        if (NoFork == 0) {
-               if (daemon(1, 0) == -1) {
+               if (daemon(0, 0) == -1) {
                        log_it("CRON", "DEATH", "can't fork");
                        exit(EXIT_FAILURE);
                }
@@ -421,8 +420,12 @@ open_socket(void)
 {
        int                sock, rc;
        mode_t             omask;
+       struct group *grp;
        struct sockaddr_un s_un;
 
+       if ((grp = getgrnam(CRON_GROUP)) == NULL)
+               log_it("CRON", "STARTUP", "can't find cron group");
+
        sock = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
        if (sock == -1) {
                fprintf(stderr, "%s: can't create socket: %s\n",
@@ -431,9 +434,9 @@ open_socket(void)
                exit(EXIT_FAILURE);
        }
        bzero(&s_un, sizeof(s_un));
-       if (strlcpy(s_un.sun_path, CRONSOCK, sizeof(s_un.sun_path))
+       if (strlcpy(s_un.sun_path, _PATH_CRON_SOCK, sizeof(s_un.sun_path))
            >= sizeof(s_un.sun_path)) {
-               fprintf(stderr, "%s: path too long\n", CRONSOCK);
+               fprintf(stderr, "%s: path too long\n", _PATH_CRON_SOCK);
                log_it("CRON", "DEATH", "path too long");
                exit(EXIT_FAILURE);
        }
@@ -463,7 +466,13 @@ open_socket(void)
                exit(EXIT_FAILURE);
        }
        chmod(s_un.sun_path, 0660);
-       chown(s_un.sun_path, -1, getegid());
+       if (grp != NULL) {
+               /* pledge won't let us change files to a foreign group. */
+               if (setegid(grp->gr_gid) == 0) {
+                       chown(s_un.sun_path, -1, grp->gr_gid);
+                       (void)setegid(getgid());
+               }
+       }
 
        return(sock);
 }
Index: usr.sbin/cron/crontab.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/crontab.c,v
retrieving revision 1.88
diff -u -p -u -r1.88 crontab.c
--- usr.sbin/cron/crontab.c     11 Nov 2015 21:20:51 -0000      1.88
+++ usr.sbin/cron/crontab.c     12 Nov 2015 16:17:47 -0000
@@ -24,6 +24,7 @@
 #include <bitstring.h>         /* for structs.h */
 #include <err.h>
 #include <errno.h>
+#include <limits.h>
 #include <locale.h>
 #include <pwd.h>
 #include <signal.h>
@@ -46,7 +47,7 @@ enum opt_t    { opt_unknown, opt_list, opt_
 static gid_t           crontab_gid;
 static gid_t           user_gid;
 static char            User[MAX_UNAME], RealUser[MAX_UNAME];
-static char            Filename[MAX_FNAME], TempFilename[MAX_FNAME];
+static char            Filename[PATH_MAX], TempFilename[PATH_MAX];
 static FILE            *NewCrontab;
 static int             CheckErrorCount;
 static enum opt_t      Option;
@@ -93,8 +94,7 @@ main(int argc, char *argv[])
 
        setvbuf(stderr, NULL, _IOLBF, 0);
        parse_args(argc, argv);         /* sets many globals, opens a file */
-       set_cron_cwd();
-       if (!allowed(RealUser, CRON_ALLOW, CRON_DENY)) {
+       if (!allowed(RealUser, _PATH_CRON_ALLOW, _PATH_CRON_DENY)) {
                fprintf(stderr, "You do not have permission to use crontab\n");
                fprintf(stderr, "See crontab(1) for more information\n");
                log_it(RealUser, "AUTH", "crontab command not allowed");
@@ -183,10 +183,7 @@ parse_args(int argc, char *argv[])
        }
 
        if (Option == opt_replace) {
-               /* we have to open the file here because we're going to
-                * chdir(2) into /var/cron before we get around to
-                * reading the file.
-                */
+               /* XXX - no longer need to open the file early, move this. */
                if (!strcmp(Filename, "-"))
                        NewCrontab = stdin;
                else {
@@ -211,12 +208,12 @@ parse_args(int argc, char *argv[])
 static void
 list_cmd(void)
 {
-       char n[MAX_FNAME];
+       char n[PATH_MAX];
        FILE *f;
 
        log_it(RealUser, "LIST", User);
-       if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n))
-               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User);
+       if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n))
+               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, 
User);
        if (!(f = fopen(n, "r"))) {
                if (errno == ENOENT)
                        warnx("no crontab for %s", User);
@@ -236,11 +233,11 @@ list_cmd(void)
 static void
 delete_cmd(void)
 {
-       char n[MAX_FNAME];
+       char n[PATH_MAX];
 
        log_it(RealUser, "DELETE", User);
-       if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n))
-               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User);
+       if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n))
+               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, 
User);
        if (unlink(n) != 0) {
                if (errno == ENOENT)
                        warnx("no crontab for %s", User);
@@ -248,7 +245,7 @@ delete_cmd(void)
                        warn("%s", n);
                exit(EXIT_FAILURE);
        }
-       poke_daemon(CRON_SPOOL, RELOAD_CRON);
+       poke_daemon(RELOAD_CRON);
 }
 
 static void
@@ -261,15 +258,15 @@ check_error(const char *msg)
 static void
 edit_cmd(void)
 {
-       char n[MAX_FNAME], q[MAX_TEMPSTR];
+       char n[PATH_MAX], q[MAX_TEMPSTR];
        FILE *f;
        int t;
        struct stat statbuf, xstatbuf;
        struct timespec ts[2];
 
        log_it(RealUser, "BEGIN EDIT", User);
-       if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n))
-               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", CRON_SPOOL, User);
+       if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= sizeof(n))
+               errc(EXIT_FAILURE, ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, 
User);
        if (!(f = fopen(n, "r"))) {
                if (errno != ENOENT)
                        err(EXIT_FAILURE, "%s", n);
@@ -393,7 +390,7 @@ edit_cmd(void)
 static int
 replace_cmd(void)
 {
-       char n[MAX_FNAME], envstr[MAX_ENVSTR];
+       char n[PATH_MAX], envstr[MAX_ENVSTR];
        FILE *tmp;
        int ch, eof, fd;
        int error = 0;
@@ -407,9 +404,9 @@ replace_cmd(void)
                return (-2);
        }
        if (snprintf(TempFilename, sizeof TempFilename, "%s/tmp.XXXXXXXXX",
-           CRON_SPOOL) >= sizeof(TempFilename)) {
+           _PATH_CRON_SPOOL) >= sizeof(TempFilename)) {
                TempFilename[0] = '\0';
-               warnc(ENAMETOOLONG, "%s/tmp.XXXXXXXXX", CRON_SPOOL);
+               warnc(ENAMETOOLONG, "%s/tmp.XXXXXXXXX", _PATH_CRON_SPOOL);
                return (-2);
        }
        if (euid != pw->pw_uid) {
@@ -505,8 +502,8 @@ replace_cmd(void)
                goto done;
        }
 
-       if (snprintf(n, sizeof n, "%s/%s", CRON_SPOOL, User) >= sizeof(n)) {
-               warnc(ENAMETOOLONG, "%s/%s", CRON_SPOOL, User);
+       if (snprintf(n, sizeof n, "%s/%s", _PATH_CRON_SPOOL, User) >= 
sizeof(n)) {
+               warnc(ENAMETOOLONG, "%s/%s", _PATH_CRON_SPOOL, User);
                error = -2;
                goto done;
        }
@@ -518,7 +515,7 @@ replace_cmd(void)
        TempFilename[0] = '\0';
        log_it(RealUser, "REPLACE", User);
 
-       poke_daemon(CRON_SPOOL, RELOAD_CRON);
+       poke_daemon(RELOAD_CRON);
 
 done:
        (void) signal(SIGHUP, SIG_DFL);
Index: usr.sbin/cron/database.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/database.c,v
retrieving revision 1.31
diff -u -p -u -r1.31 database.c
--- usr.sbin/cron/database.c    9 Nov 2015 16:37:07 -0000       1.31
+++ usr.sbin/cron/database.c    12 Nov 2015 16:17:47 -0000
@@ -38,9 +38,8 @@
 
 #define HASH(a,b) ((a)+(b))
 
-static void            process_crontab(const char *, const char *,
-                                       const char *, struct stat *,
-                                       cron_db *, cron_db *);
+static void            process_crontab(int, const char *, const char *,
+                                       struct stat *, cron_db *, cron_db *);
 
 void
 load_database(cron_db **db)
@@ -51,18 +50,18 @@ load_database(cron_db **db)
        DIR *dir;
        user *u;
 
-       /* before we start loading any data, do a stat on CRON_SPOOL
+       /* before we start loading any data, do a stat on _PATH_CRON_SPOOL
         * so that if anything changes as of this moment (i.e., before we've
         * cached any of the database), we'll see the changes next time.
         */
-       if (stat(CRON_SPOOL, &statbuf) < 0) {
-               log_it("CRON", "STAT FAILED", CRON_SPOOL);
+       if (stat(_PATH_CRON_SPOOL, &statbuf) < 0) {
+               log_it("CRON", "STAT FAILED", _PATH_CRON_SPOOL);
                return;
        }
 
        /* track system crontab file
         */
-       if (stat(SYSCRONTAB, &syscron_stat) < 0)
+       if (stat(_PATH_SYS_CRONTAB, &syscron_stat) < 0)
                syscron_stat.st_mtime = 0;
 
        /* if spooldir's mtime has not changed, we don't need to fiddle with
@@ -84,16 +83,16 @@ load_database(cron_db **db)
        TAILQ_INIT(&new_db->users);
 
        if (syscron_stat.st_mtime) {
-               process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
-                               new_db, old_db);
+               process_crontab(AT_FDCWD, "*system*", _PATH_SYS_CRONTAB,
+                               &syscron_stat, new_db, old_db);
        }
 
        /* we used to keep this dir open all the time, for the sake of
         * efficiency.  however, we need to close it in every fork, and
         * we fork a lot more often than the mtime of the dir changes.
         */
-       if (!(dir = opendir(CRON_SPOOL))) {
-               log_it("CRON", "OPENDIR FAILED", CRON_SPOOL);
+       if (!(dir = opendir(_PATH_CRON_SPOOL))) {
+               log_it("CRON", "OPENDIR FAILED", _PATH_CRON_SPOOL);
                /* Restore system crontab entry as needed. */
                if (!TAILQ_EMPTY(&new_db->users) &&
                    (u = TAILQ_FIRST(&old_db->users))) {
@@ -109,8 +108,6 @@ load_database(cron_db **db)
        }
 
        while (NULL != (dp = readdir(dir))) {
-               char fname[NAME_MAX+1], tabname[MAX_FNAME];
-
                /* avoid file names beginning with ".".  this is good
                 * because we would otherwise waste two guaranteed calls
                 * to getpwnam() for . and .., and also because user names
@@ -119,14 +116,7 @@ load_database(cron_db **db)
                if (dp->d_name[0] == '.')
                        continue;
 
-               if (strlcpy(fname, dp->d_name, sizeof fname) >= sizeof fname)
-                       continue;       /* XXX log? */
-
-               if (snprintf(tabname, sizeof tabname, "%s/%s", CRON_SPOOL, 
fname) >=
-                       sizeof(tabname))
-                       continue;       /* XXX log? */
-
-               process_crontab(fname, fname, tabname,
+               process_crontab(dirfd(dir), dp->d_name, dp->d_name,
                                &statbuf, new_db, old_db);
        }
        closedir(dir);
@@ -167,53 +157,51 @@ find_user(cron_db *db, const char *name)
 }
 
 static void
-process_crontab(const char *uname, const char *fname, const char *tabname,
+process_crontab(int dfd, const char *uname, const char *fname,
                struct stat *statbuf, cron_db *new_db, cron_db *old_db)
 {
        struct passwd *pw = NULL;
        int crontab_fd = -1;
        user *u;
 
-       if (fname == NULL) {
-               /* must be set to something for logging purposes.
-                */
-               fname = "*system*";
-       } else if ((pw = getpwnam(uname)) == NULL) {
+       /* Note: pw must remain NULL for system crontab (see below). */
+       if (fname[0] != '/' && (pw = getpwnam(uname)) == NULL) {
                /* file doesn't have a user in passwd file.
                 */
-               log_it(fname, "ORPHAN", "no passwd entry");
+               log_it(uname, "ORPHAN", "no passwd entry");
                goto next_crontab;
        }
 
-       if ((crontab_fd = open(tabname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 
0) {
+       crontab_fd = openat(dfd, fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
+       if (crontab_fd < 0) {
                /* crontab not accessible?
                 */
-               log_it(fname, "CAN'T OPEN", tabname);
+               log_it(uname, "CAN'T OPEN", fname);
                goto next_crontab;
        }
 
        if (fstat(crontab_fd, statbuf) < 0) {
-               log_it(fname, "FSTAT FAILED", tabname);
+               log_it(uname, "FSTAT FAILED", fname);
                goto next_crontab;
        }
        if (!S_ISREG(statbuf->st_mode)) {
-               log_it(fname, "NOT REGULAR", tabname);
+               log_it(uname, "NOT REGULAR", fname);
                goto next_crontab;
        }
-       if ((statbuf->st_mode & 07577) != 0400) {
+       if (pw != NULL) {
                /* Looser permissions on system crontab. */
-               if (pw != NULL || (statbuf->st_mode & 022) != 0) {
-                       log_it(fname, "BAD FILE MODE", tabname);
+               if ((statbuf->st_mode & 077) != 0) {
+                       log_it(uname, "BAD FILE MODE", fname);
                        goto next_crontab;
                }
        }
        if (statbuf->st_uid != 0 && (pw == NULL ||
            statbuf->st_uid != pw->pw_uid || strcmp(uname, pw->pw_name) != 0)) {
-               log_it(fname, "WRONG FILE OWNER", tabname);
+               log_it(uname, "WRONG FILE OWNER", fname);
                goto next_crontab;
        }
        if (pw != NULL && statbuf->st_nlink != 1) {
-               log_it(fname, "BAD LINK COUNT", tabname);
+               log_it(uname, "BAD LINK COUNT", fname);
                goto next_crontab;
        }
 
@@ -237,7 +225,7 @@ process_crontab(const char *uname, const
                 */
                TAILQ_REMOVE(&old_db->users, u, entries);
                free_user(u);
-               log_it(fname, "RELOAD", tabname);
+               log_it(uname, "RELOAD", fname);
        }
        u = load_user(crontab_fd, pw, fname);
        if (u != NULL) {
Index: usr.sbin/cron/funcs.h
===================================================================
RCS file: /cvs/src/usr.sbin/cron/funcs.h,v
retrieving revision 1.26
diff -u -p -u -r1.26 funcs.h
--- usr.sbin/cron/funcs.h       9 Nov 2015 16:37:07 -0000       1.26
+++ usr.sbin/cron/funcs.h       12 Nov 2015 16:17:47 -0000
@@ -22,8 +22,7 @@
  *     We should reorg this into sections by module.
  */
 
-void           set_cron_cwd(void),
-               load_database(cron_db **),
+void           load_database(cron_db **),
                job_add(entry *, user *),
                do_command(entry *, user *),
                free_user(user *),
@@ -33,7 +32,7 @@ void          set_cron_cwd(void),
                skip_comments(FILE *),
                log_it(const char *, const char *, const char *),
                log_close(void),
-               poke_daemon(const char *, unsigned char),
+               poke_daemon(unsigned char),
                atrun(at_db *, double, time_t);
 
 int            job_runqueue(void),
@@ -44,8 +43,6 @@ int           job_runqueue(void),
                allowed(const char *, const char *, const char *),
                safe_p(const char *, const char *),
                scan_atjobs(at_db **, struct timespec *);
-
-int            strtot(const char *nptr, char **endptr, time_t *tp);
 
 char           *env_get(char *, char **),
                *first_word(char *, char *),
Index: usr.sbin/cron/macros.h
===================================================================
RCS file: /cvs/src/usr.sbin/cron/macros.h,v
retrieving revision 1.14
diff -u -p -u -r1.14 macros.h
--- usr.sbin/cron/macros.h      4 Nov 2015 20:28:17 -0000       1.14
+++ usr.sbin/cron/macros.h      12 Nov 2015 16:17:47 -0000
@@ -24,7 +24,6 @@
 
 #define READ_PIPE      0       /* which end of a pipe pair do you read? */
 #define WRITE_PIPE     1       /*   or write to? */
-#define        MAX_FNAME       100     /* max length of internally generated 
fn */
 #define        MAX_COMMAND     1000    /* max length of internally generated 
cmd */
 #define        MAX_ENVSTR      1000    /* max length of envvar=value\0 strings 
*/
 #define        MAX_TEMPSTR     100     /* obvious */
Index: usr.sbin/cron/pathnames.h
===================================================================
RCS file: /cvs/src/usr.sbin/cron/pathnames.h,v
retrieving revision 1.21
diff -u -p -u -r1.21 pathnames.h
--- usr.sbin/cron/pathnames.h   12 Nov 2015 13:42:42 -0000      1.21
+++ usr.sbin/cron/pathnames.h   12 Nov 2015 16:17:47 -0000
@@ -22,56 +22,15 @@
 
 #include <paths.h>
 
-                       /* CRONDIR is where cron(8), crontab(1) and at(1)
-                        * chdir to; CRON_SPOOL, CRON_ALLOW, CRON_DENY,
-                        * AT_SPOOL, AT_ALLOW and AT_DENY are all relative
-                        * to this directory.
-                        */
-#define CRONDIR                "/var/cron"
-
-                       /* SPOOLDIR is where the crontabs live.
-                        * This directory will have its modtime updated
-                        * whenever crontab(1) changes a crontab; this is
-                        * the signal for cron(8) to look at each individual
-                        * crontab file and reload those whose modtimes are
-                        * newer than they were last time around (or which
-                        * didn't exist last time around...)
-                        */
-#define CRON_SPOOL     "tabs"
-
-                       /* AT_SPOOL is where the at jobs live (relative to
-                        * CRONDIR). This directory will have its modtime
-                        * updated whenever at(1) changes a crontab; this is
-                        * the signal for cron(8) to look for changes in the
-                        * jobs directory (new, changed or jobs).
-                        */
-#define AT_SPOOL       "atjobs"
-
-                       /* CRONSOCK is the name of the socket used by at and
-                        * crontab to poke cron to re-read the at and cron
-                        * spool files while cron is asleep.
-                        */
-#define        CRONSOCK        "/var/run/cron.sock"
-#define        CRONSOCK_OLD    CRON_SPOOL "/.sock"
-
-                       /* cron allow/deny file.  At least cron.deny must
-                        * exist for ordinary users to run crontab.
-                        */
-#define        CRON_ALLOW      "cron.allow"
-#define        CRON_DENY       "cron.deny"
-
-                       /* at allow/deny file.  At least at.deny must
-                        * exist for ordinary users to run at.
-                        */
-#define        AT_ALLOW        "at.allow"
-#define        AT_DENY         "at.deny"
-
-                       /* 4.3BSD-style crontab */
-#define SYSCRONTAB     "/etc/crontab"
-
-                       /* what editor to use if no EDITOR or VISUAL
-                        * environment variable specified.
-                        */
-#define EDITOR         _PATH_VI
+#define _PATH_CRON_DIR         "/var/cron/"
+#define _PATH_CRON_SPOOL       _PATH_CRON_DIR "tabs"
+#define _PATH_AT_SPOOL         _PATH_CRON_DIR "atjobs"
+#define        _PATH_CRON_SOCK         "/var/run/cron.sock"
+#define        _PATH_CRON_SOCK_OLD     _PATH_CRON_SPOOL "/.sock"
+#define        _PATH_CRON_ALLOW        _PATH_CRON_DIR "cron.allow"
+#define        _PATH_CRON_DENY         _PATH_CRON_DIR "cron.deny"
+#define        _PATH_AT_ALLOW          _PATH_CRON_DIR "at.allow"
+#define        _PATH_AT_DENY           _PATH_CRON_DIR "at.deny"
+#define _PATH_SYS_CRONTAB      "/etc/crontab"
 
 #endif /* _PATHNAMES_H_ */
Index: usr.bin/at/Makefile
===================================================================
RCS file: /cvs/src/usr.bin/at/Makefile,v
retrieving revision 1.10
diff -u -p -u -r1.10 Makefile
--- usr.bin/at/Makefile 31 Oct 2015 12:19:41 -0000      1.10
+++ usr.bin/at/Makefile 12 Nov 2015 16:17:47 -0000
@@ -1,7 +1,7 @@
 #      $OpenBSD: Makefile,v 1.10 2015/10/31 12:19:41 millert Exp $
 
 PROG=  at
-SRCS=  at.c client.c common.c parsetime.c
+SRCS=  at.c client.c parsetime.c
 CRONDIR=${.CURDIR}/../../usr.sbin/cron
 CFLAGS+=-I${CRONDIR}
 MAN=   at.1 atrm.1 atq.1
Index: usr.bin/at/at.c
===================================================================
RCS file: /cvs/src/usr.bin/at/at.c,v
retrieving revision 1.73
diff -u -p -u -r1.73 at.c
--- usr.bin/at/at.c     11 Nov 2015 21:53:51 -0000      1.73
+++ usr.bin/at/at.c     12 Nov 2015 16:17:47 -0000
@@ -70,7 +70,7 @@ char *no_export[] =
 };
 
 int program = AT;              /* default program mode */
-char atfile[MAX_FNAME];                /* path to the at spool file */
+char atfile[PATH_MAX];         /* path to the at spool file */
 int fcreated;                  /* whether or not we created the file yet */
 char atqueue = 0;              /* which queue to examine for jobs (atq) */
 char vflag = 0;                        /* show completed but unremoved jobs 
(atq) */
@@ -142,6 +142,21 @@ sigc(int signo)
 }
 
 static int
+strtot(const char *nptr, char **endptr, time_t *tp)
+{
+       long long ll;
+
+       errno = 0;
+       ll = strtoll(nptr, endptr, 10);
+       if (*endptr == nptr)
+               return (-1);
+       if (ll < 0 || (errno == ERANGE && ll == LLONG_MAX) || (time_t)ll != ll)
+               return (-1);
+       *tp = (time_t)ll;
+       return (0);
+}
+
+static int
 newjob(time_t runtimer, int queue)
 {
        int fd, i;
@@ -152,7 +167,7 @@ newjob(time_t runtimer, int queue)
         * queues instead...
         */
        for (i = 0; i < 120; i++) {
-               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", AT_SPOOL,
+               snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
                    (long long)runtimer, queue);
                fd = open(atfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
                if (fd >= 0)
@@ -351,12 +366,12 @@ writefile(const char *cwd, time_t runtim
        (void)fclose(fp);
 
        /* Poke cron so it knows to reload the at spool. */
-       poke_daemon(AT_SPOOL, RELOAD_AT);
+       poke_daemon(RELOAD_AT);
 
        runtime = *localtime(&runtimer);
        strftime(timestr, TIMESIZE, "%a %b %e %T %Y", &runtime);
        (void)fprintf(stderr, "commands will be executed using %s\n", shell);
-       (void)fprintf(stderr, "job %s at %s\n", &atfile[sizeof(AT_SPOOL)],
+       (void)fprintf(stderr, "job %s at %s\n", &atfile[sizeof(_PATH_AT_SPOOL)],
            timestr);
 }
 
@@ -414,7 +429,7 @@ print_job(struct atjob *job, int n, int 
 
 /*
  * List all of a user's jobs in the queue, by looping through
- * AT_SPOOL, or all jobs if we are root.  If argc is > 0, argv
+ * _PATH_AT_SPOOL, or all jobs if we are root.  If argc is > 0, argv
  * contains the list of users whose jobs shall be displayed. By
  * default, the list is sorted by execution date and queue.  If
  * csort is non-zero jobs will be sorted by creation/submission date.
@@ -449,12 +464,12 @@ list_jobs(int argc, char **argv, int cou
 
        shortformat = strcmp(__progname, "at") == 0;
 
-       if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 ||
+       if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 ||
            (spool = fdopendir(dfd)) == NULL)
-               fatal(AT_SPOOL);
+               fatal(_PATH_AT_SPOOL);
 
        if (fstat(dfd, &stbuf) != 0)
-               fatal(AT_SPOOL);
+               fatal(_PATH_AT_SPOOL);
 
        /*
         * The directory's link count should give us a good idea
@@ -564,7 +579,7 @@ rmok(long long job)
 }
 
 /*
- * Loop through all jobs in AT_SPOOL and display or delete ones
+ * Loop through all jobs in _PATH_AT_SPOOL and display or delete ones
  * that match argv (may be job or username), or all if argc == 0.
  * Only the superuser may display/delete other people's jobs.
  */
@@ -583,9 +598,9 @@ process_jobs(int argc, char **argv, int 
        int job_matches, jobs_len, uids_len;
        int error, i, ch, changed, dfd;
 
-       if ((dfd = open(AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 ||
+       if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1 ||
            (spool = fdopendir(dfd)) == NULL)
-               fatal(AT_SPOOL);
+               fatal(_PATH_AT_SPOOL);
 
        /* Convert argv into a list of jobs and uids. */
        jobs = NULL;
@@ -696,7 +711,7 @@ process_jobs(int argc, char **argv, int 
 
        /* If we modied the spool, poke cron so it knows to reload. */
        if (changed)
-               poke_daemon(AT_SPOOL, RELOAD_AT);
+               poke_daemon(RELOAD_AT);
 
        return (error);
 }
@@ -792,7 +807,7 @@ check_permission(void)
        if ((pw = getpwuid(user_uid)) == NULL)
                fatalx("unknown uid %u", user_uid);
 
-       return (allowed(pw->pw_name, AT_ALLOW, AT_DENY));
+       return (allowed(pw->pw_name, _PATH_AT_ALLOW, _PATH_AT_DENY));
 }
 
 static __dead void
@@ -963,8 +978,6 @@ main(int argc, char **argv)
 
        if (getcwd(cwd, sizeof(cwd)) == NULL)
                fatal("unable to get current working directory");
-
-       set_cron_cwd();
 
        if (!check_permission())
                fatalx("you do not have permission to use at.");

Reply via email to