diff options
Diffstat (limited to 'usr/src/cmd/cron')
-rw-r--r-- | usr/src/cmd/cron/Makefile | 53 | ||||
-rw-r--r-- | usr/src/cmd/cron/cron.c | 154 | ||||
-rw-r--r-- | usr/src/cmd/cron/cron.h | 4 | ||||
-rw-r--r-- | usr/src/cmd/cron/crontab.c | 40 | ||||
-rw-r--r-- | usr/src/cmd/cron/crontab.root | 18 | ||||
-rw-r--r-- | usr/src/cmd/cron/svc-cron | 42 |
6 files changed, 238 insertions, 73 deletions
diff --git a/usr/src/cmd/cron/Makefile b/usr/src/cmd/cron/Makefile index 9a555562d8..405b7d5f61 100644 --- a/usr/src/cmd/cron/Makefile +++ b/usr/src/cmd/cron/Makefile @@ -28,6 +28,7 @@ DEFAULTFILES = cron.dfl include ../Makefile.cmd +include ../Makefile.ctf MANIFEST = cron.xml @@ -47,6 +48,7 @@ ROOTVAR = $(ROOT)/var ROOTSPCRON = $(ROOTVAR)/spool/cron ROOTCROND = $(ROOTETC)/cron.d +ROOTCRONDCRONTABS = $(ROOTCROND)/crontabs ROOTCRONTABS = $(ROOTSPCRON)/crontabs ROOTATJOBS = $(ROOTSPCRON)/atjobs ROOTLIBCRON = $(ROOTLIB)/cron @@ -66,9 +68,6 @@ POFILES1= at.po crontab.po funcs.po batch.po POFILES= $(POFILES1) atrm.po $(POFILES1) := XGETFLAGS= -a -x $(PROG1).xcl -ROOTDIRS = $(ROOTSPCRON) $(ROOTCROND) \ - $(ROOTCRONTABS) $(ROOTATJOBS) - ROOTPROG = $(PROG1:%=$(ROOTUSRSBIN)/%) $(PROG2:%=$(ROOTBIN)/%) \ $(SCRIPT:%=$(ROOTBIN)/%) \ $(XPG6PROG:%=$(ROOTXPG6BIN)/%) \ @@ -102,21 +101,21 @@ XPG4ATOBJS= $(ATOBJS:%=objs.xpg4/%) $(XPG4OBJS:%=objs.xpg4/%) XPG6COMMONOBJS= $(COMMONOBJS:%=objs.xpg6/%) XPG6CTOBJS= $(CRONTABOBJS:%=objs.xpg6/%) -cron := POBJS = $(CRONOBJS) $(COMMONOBJ2) -at := POBJS = $(ATOBJS) $(COMMONOBJS) -at.xpg4 := POBJS = $(XPG4ATOBJS) $(XPG4COMMONOBJS) -atrm := POBJS = $(ATRMOBJS) $(COMMONOBJS) -atq := POBJS = $(ATQOBJS) $(COMMONOBJS) -crontab := POBJS = $(CRONTABOBJS) $(COMMONOBJS) -crontab.xpg4 := POBJS = $(XPG4CTOBJS) $(XPG4COMMONOBJS) -crontab.xpg6 := POBJS = $(XPG6CTOBJS) $(XPG6COMMONOBJS) -parsetest := POBJS = $(PARSETESTOBJS) +cron := OBJS = $(CRONOBJS) $(COMMONOBJ2) +at := OBJS = $(ATOBJS) $(COMMONOBJS) +at.xpg4 := OBJS = $(XPG4ATOBJS) $(XPG4COMMONOBJS) +atrm := OBJS = $(ATRMOBJS) $(COMMONOBJS) +atq := OBJS = $(ATQOBJS) $(COMMONOBJS) +crontab := OBJS = $(CRONTABOBJS) $(COMMONOBJS) +crontab.xpg4 := OBJS = $(XPG4CTOBJS) $(XPG4COMMONOBJS) +crontab.xpg6 := OBJS = $(XPG6CTOBJS) $(XPG6COMMONOBJS) +parsetest := OBJS = $(PARSETESTOBJS) CFLAGS += $(CCVERBOSE) NOBJS= $(CRONOBJS) $(ATOBJS) $(ATRMOBJS1) $(ATQOBJS) $(CRONTABOBJS1) \ $(COMMONOBJS) -OBJS = $(NOBJS) $(XPG4COMMONOBJS) $(XPG4ATOBJS) $(XPG4CTOBJS) \ +COBJS = $(NOBJS) $(XPG4COMMONOBJS) $(XPG4ATOBJS) $(XPG4CTOBJS) \ $(XPG6COMMONOBJS) $(XPG6CTOBJS) $(GETRESPOBJ) SRCS = $(NOBJS:%.o=%.c) $(GETRESPSRC) @@ -159,34 +158,37 @@ all : $(PROG) $(XPG4) $(XPG6) $(SCRIPT) $(XPG4SCRIPT) $(FILES) \ $(PARSETEST) install : all $(ROOTPROG) $(ROOTETCDEFAULTFILES) $(ROOTSYMLINK) \ - $(ROOTMANIFEST) $(ROOTMETHOD) + $(ROOTMANIFEST) $(ROOTMETHOD) $(ROOTCRONDCRONTABS)/root -$(PROG) $(PARSETEST): $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(PROG) $(PARSETEST): $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) -$(XPG4) : objs.xpg4 $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(XPG4) : objs.xpg4 $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) -$(XPG6) : objs.xpg6 $$(POBJS) - $(LINK.c) $(POBJS) -o $@ $(LDLIBS) +$(XPG6) : objs.xpg6 $$(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) objs.xpg6/%.o: %.c $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) objs.xpg6: -@mkdir -p $@ objs.xpg4/%.o: %.c $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) objs.xpg4: -@mkdir -p $@ objs.xpg4/values-xpg4.o: ../../lib/crt/common/values-xpg4.c $(COMPILE.c) -o $@ ../../lib/crt/common/values-xpg4.c + $(POST_PROCESS_O) %.o: $(SRC)/common/util/%.c $(COMPILE.c) $(OUTPUT_OPTION) $< @@ -210,20 +212,21 @@ att2.c : att2.l att2.ed att1.c ed - lex.yy.c < att2.ed $(MV) lex.yy.c att2.c -# Don't re-install directories installed by Targetdirs -#$(ROOTDIRS): -# $(INS.dir) - $(ROOTSYMLINK) : $(RM) $@; $(SYMLINK) $(SYMLNKDEST) $@ +$(ROOTCRONDCRONTABS)/root: crontab.root + $(RM) $@; \ + $(INS) -s -m $(FILEMODE) -f $(@D) crontab.root; \ + $(MV) $(@D)/crontab.root $@ + check: $(CHKMANIFEST) $(POFILE): $(POFILES) $(RM) $@; cat $(POFILES) > $@ clean : - $(RM) $(OBJS) att1.h att1.c att2.c + $(RM) $(COBJS) att1.h att1.c att2.c strip : $(STRIP) $(PROG) $(XPG4) $(XPG6) diff --git a/usr/src/cmd/cron/cron.c b/usr/src/cmd/cron/cron.c index 1be2e71968..26abd30d18 100644 --- a/usr/src/cmd/cron/cron.c +++ b/usr/src/cmd/cron/cron.c @@ -23,7 +23,7 @@ * Use is subject to license terms. * * Copyright 2013 Joshua M. Clulow <josh@sysmgr.org> - * + * Copyright 2013 Joyent, Inc. All rights reserved. * Copyright (c) 2014 Gary Mills * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. @@ -313,7 +313,8 @@ static struct usr *find_usr(char *); static int ex(struct event *e); static void read_dirs(int); static void mail(char *, char *, int); -static void readcron(struct usr *, time_t); +static void readcron(char *, struct usr *, time_t); +static void readcronfile(FILE *, struct usr *, time_t); static int next_ge(int, char *); static void free_if_unused(struct usr *); static void del_atjob(char *, char *); @@ -418,7 +419,7 @@ extern void el_delete(void); static int valid_entry(char *, int); static struct usr *create_ulist(char *, int); -static void init_cronevent(char *, int); +static void init_cronevent(char *, char *); static void init_atevent(char *, time_t, int, int); static void update_atevent(struct usr *, char *, time_t, int); @@ -757,6 +758,18 @@ read_dirs(int first) time_t tim; + if (chdir(SYSCRONDIR) != -1) { + cwd = CRON; + if ((dir = opendir(".")) != NULL) { + while ((dp = readdir(dir)) != NULL) { + if (!valid_entry(dp->d_name, CRONEVENT)) + continue; + init_cronevent(SYSCRONDIR, dp->d_name); + } + (void) closedir(dir); + } + } + if (chdir(CRONDIR) == -1) crabort(BADCD, REMOVE_FIFO|CONSOLE_MSG); cwd = CRON; @@ -765,7 +778,7 @@ read_dirs(int first) while ((dp = readdir(dir)) != NULL) { if (!valid_entry(dp->d_name, CRONEVENT)) continue; - init_cronevent(dp->d_name, first); + init_cronevent(CRONDIR, dp->d_name); } (void) closedir(dir); @@ -851,23 +864,18 @@ create_ulist(char *name, int type) } void -init_cronevent(char *name, int first) +init_cronevent(char *basedir, char *name) { struct usr *u; - if (first) { + if ((u = find_usr(name)) == NULL) { u = create_ulist(name, CRONEVENT); - readcron(u, 0); + readcron(basedir, u, 0); } else { - if ((u = find_usr(name)) == NULL) { - u = create_ulist(name, CRONEVENT); - readcron(u, 0); - } else { - u->ctexists = TRUE; - rm_ctevents(u); - el_remove(u->ctid, 0); - readcron(u, 0); - } + u->ctexists = TRUE; + rm_ctevents(u); + el_remove(u->ctid, 0); + readcron(basedir, u, 0); } } @@ -948,7 +956,7 @@ mod_ctab(char *name, time_t reftime) (void) strcpy(u->home, pw->pw_dir); u->uid = pw->pw_uid; u->gid = pw->pw_gid; - readcron(u, reftime); + readcron(CRONDIR, u, reftime); } else { u->uid = pw->pw_uid; u->gid = pw->pw_gid; @@ -971,7 +979,7 @@ mod_ctab(char *name, time_t reftime) /* user didnt have a crontab last time */ u->ctid = ecid++; u->ctevents = NULL; - readcron(u, reftime); + readcron(CRONDIR, u, reftime); return; } #ifdef DEBUG @@ -980,7 +988,7 @@ mod_ctab(char *name, time_t reftime) #endif rm_ctevents(u); el_remove(u->ctid, 0); - readcron(u, reftime); + readcron(CRONDIR, u, reftime); } } @@ -1114,8 +1122,94 @@ update_atevent(struct usr *u, char *name, time_t tim, int jobtype) static char line[CTLINESIZE]; /* holds a line from a crontab file */ static int cursor; /* cursor for the above line */ +static int +copyfile(char *name, FILE *dp) +{ + FILE *tf; + + if ((tf = fopen(name, "r")) == NULL) { + (void) fclose(dp); + return (1); + } + + while (fgets(line, CTLINESIZE, tf) != NULL) { + if (fputs(line, dp) == EOF) { + (void) fclose(tf); + (void) fclose(dp); + return (1); + } + } + (void) fclose(tf); + + return (0); +} + +static void +readcron(char *basedir, struct usr *u, time_t reftime) +{ + char *altpath; + struct stat sb; + FILE *cf; /* cf will be a user's crontab file */ + char altnamebuf[PATH_MAX]; + char namebuf[PATH_MAX]; + + if (strcmp(basedir, SYSCRONDIR) == 0) + altpath = CRONDIR; + else + altpath = SYSCRONDIR; + + if (snprintf(altnamebuf, sizeof (altnamebuf), "%s/%s", altpath, + u->name) >= sizeof (altnamebuf)) + return; + + if (snprintf(namebuf, sizeof (namebuf), "%s/%s", basedir, u->name) >= + sizeof (namebuf)) + return; + + if (stat(altnamebuf, &sb) != -1) { + /* + * There is a secondary crontab for this user. We need to + * merge the two crontabs into a temporary file for loading. + */ + int fd; + char tmpfile[PATH_MAX]; + + (void) strlcpy(tmpfile, "/tmp/cronXXXXXX", sizeof (tmpfile)); + if ((fd = mkstemp(tmpfile)) == -1) + return; + + unlink(tmpfile); + if ((cf = fdopen(fd, "w+")) == NULL) { + close(fd); + return; + } + + if (copyfile(namebuf, cf) != 0) + return; + + if (copyfile(altnamebuf, cf) != 0) + return; + + (void) fflush(cf); + rewind(cf); + + } else { + /* + * Only one crontab, open it directly. + */ + if ((cf = fopen(namebuf, "r")) == NULL) { + mail(u->name, NOREAD, ERR_UNIXERR); + return; + } + } + + readcronfile(cf, u, reftime); + + (void) fclose(cf); +} + static void -readcron(struct usr *u, time_t reftime) +readcronfile(FILE *cf, struct usr *u, time_t reftime) { /* * readcron reads in a crontab file for a user (u). The list of @@ -1123,12 +1217,9 @@ readcron(struct usr *u, time_t reftime) * this list. Each event is also entered into the main event * list. */ - FILE *cf; /* cf will be a user's crontab file */ struct event *e; int start; unsigned int i; - char namebuf[PATH_MAX]; - char *pname; struct shared *tz = NULL; struct shared *home = NULL; struct shared *shell = NULL; @@ -1138,19 +1229,6 @@ readcron(struct usr *u, time_t reftime) /* read the crontab file */ cte_init(); /* Init error handling */ - if (cwd != CRON) { - if (snprintf(namebuf, sizeof (namebuf), "%s/%s", - CRONDIR, u->name) >= sizeof (namebuf)) { - return; - } - pname = namebuf; - } else { - pname = u->name; - } - if ((cf = fopen(pname, "r")) == NULL) { - mail(u->name, NOREAD, ERR_UNIXERR); - return; - } while (fgets(line, CTLINESIZE, cf) != NULL) { char *tmp; /* process a line of a crontab file */ @@ -1305,7 +1383,6 @@ again: #endif } cte_sendmail(u->name); /* mail errors if any to user */ - (void) fclose(cf); rel_shared(tz); rel_shared(shell); rel_shared(home); @@ -2411,6 +2488,9 @@ ex(struct event *e) } else { r = audit_cron_session(e->u->name, CRONDIR, e->u->uid, e->u->gid, NULL); + if (r != 0) + r = audit_cron_session(e->u->name, SYSCRONDIR, + e->u->uid, e->u->gid, NULL); } if (r != 0) { msg("cron audit problem. job failed (%s) for user %s", diff --git a/usr/src/cmd/cron/cron.h b/usr/src/cmd/cron/cron.h index b2e241f202..743fde1d24 100644 --- a/usr/src/cmd/cron/cron.h +++ b/usr/src/cmd/cron/cron.h @@ -76,6 +76,10 @@ struct message { char logname[LLEN]; }; +/* anything below here can be changed */ + +#define SYSCRONDIR "/etc/cron.d/crontabs" + /* * Errors from the crontab field parser. */ diff --git a/usr/src/cmd/cron/crontab.c b/usr/src/cmd/cron/crontab.c index 4ff985240e..fad9131ad0 100644 --- a/usr/src/cmd/cron/crontab.c +++ b/usr/src/cmd/cron/crontab.c @@ -74,8 +74,8 @@ #define BADUSAGE \ "usage:\n" \ "\tcrontab [-u username] [file]\n" \ - "\tcrontab [-u username] { -e | -l | -r }\n" \ - "\tcrontab { -e | -l | -r } [username]" + "\tcrontab [-u username] { -e | -g | -l | -r }\n" \ + "\tcrontab { -e | -g | -l | -r } [username]" #define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)." #define NOTALLOWED "you are not authorized to use cron. Sorry." #define NOTROOT \ @@ -124,6 +124,7 @@ main(int argc, char **argv) int c, r; int rflag = 0; int lflag = 0; + int gflag = 0; int eflag = 0; int errflg = 0; char *pp; @@ -156,11 +157,14 @@ main(int argc, char **argv) exit(1); } - while ((c = getopt(argc, argv, "elru:")) != EOF) { + while ((c = getopt(argc, argv, "eglru:")) != EOF) { switch (c) { case 'e': eflag++; break; + case 'g': + gflag++; + break; case 'l': lflag++; break; @@ -182,6 +186,9 @@ main(int argc, char **argv) if (eflag + lflag + rflag > 1) errflg++; + if (gflag && !lflag) + errflg++; + if ((eflag || lflag || rflag) && argc > 0) { if (user != NULL) errflg++; @@ -255,12 +262,27 @@ main(int argc, char **argv) exit(0); } if (lflag) { - if ((fp = fopen(cf, "r")) == NULL) - crabort(BADOPEN); - while (fgets(line, CTLINESIZE, fp) != NULL) - fputs(line, stdout); - fclose(fp); - exit(0); + char sysconf[PATH_MAX]; + + if (gflag) { + if (snprintf(sysconf, sizeof (sysconf), "%s/%s", + SYSCRONDIR, login) < sizeof (sysconf) && + (fp = fopen(sysconf, "r")) != NULL) { + while (fgets(line, CTLINESIZE, fp) != NULL) + fputs(line, stdout); + fclose(fp); + exit(0); + } else { + crabort(BADOPEN); + } + } else { + if ((fp = fopen(cf, "r")) == NULL) + crabort(BADOPEN); + while (fgets(line, CTLINESIZE, fp) != NULL) + fputs(line, stdout); + fclose(fp); + exit(0); + } } if (eflag) { if ((fp = fopen(cf, "r")) == NULL) { diff --git a/usr/src/cmd/cron/crontab.root b/usr/src/cmd/cron/crontab.root new file mode 100644 index 0000000000..4153ad2d6a --- /dev/null +++ b/usr/src/cmd/cron/crontab.root @@ -0,0 +1,18 @@ +## Rotate and trim the audit logs nightly. +0 0 * * * /smartdc/bin/sdc-lastcomm -R 30 +## Run logadm hourly so that the minimum rotate interval is 1h +0 * * * * /usr/sbin/logadm +## Rotate vm.log files for any KVM VMs +0 * * * * SDC_LOG_ROLL_BACKWARD=1 /usr/vm/sbin/rotate-kvm-logs.sh >> /var/log/rotate-kvm-logs.log 2>&1 +## Headnode should phone home nightly. +0 1 * * * [ -x /opt/smartdc/bin/sdc-phonehome ] && /opt/smartdc/bin/sdc-phonehome +## Delete saved core dumps over 7 days old +15 0 * * * find /zones/*/cores -type f -mtime +7 -exec rm -f "{}" \; +## Delete archived zone data over 7 days old +30 0 * * * find /zones/archive/ -mount -maxdepth 1 -mindepth 1 -type d -mtime +7 -exec rm -rf "{}" \; +## Delete logs to be uploaded over 7 days old if they aren't being consumed +45 0 * * * [ -d /var/log/sdc/upload/ ] && find /var/log/sdc/upload/ -mount -maxdepth 1 -mindepth 1 -type f -mtime +7 -exec rm -f "{}" \; + +# NOTE: all entries above are in root's system-defined crontab; see the +# crontab(1) man page. + diff --git a/usr/src/cmd/cron/svc-cron b/usr/src/cmd/cron/svc-cron index 4def6071b8..55033608ee 100644 --- a/usr/src/cmd/cron/svc-cron +++ b/usr/src/cmd/cron/svc-cron @@ -22,8 +22,7 @@ # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright 2012 Joyent, Inc. All rights reserved. # # Start method script for the cron service. # @@ -37,6 +36,45 @@ if [ -p /etc/cron.d/FIFO ]; then fi fi +if smf_is_globalzone && [ -n "$(bootparams | grep '^headnode=true')" ]; then + # + # Randomize root's crontab so all HN's are not in sync. + # + utc_offset=`nawk -F= '{if ($1 == "utc_offset") print $2}' \ + /usbkey/config.inc/generic` + [ -z "$utc_offset" ] && utc_offset=0 + + n=$(date +%S) + hr=$(($n % 5)) + hr=$(($hr + $utc_offset)) + + n=$(date +%M) + mn=$(($n % 15)) + + nawk -v hr=$hr -v mn=$mn '{ + if (substr($1, 1, 1) == "#") { + print $0 + next + } + if (substr($2, 1, 1) == "*") { + print $0 + next + } + if (length($0) == 0) { + print $0 + next + } + + printf("%d %d %s %s %s %s", mn, hr, $3, $4, $5, $6) + for (i = 7; i <= NF; i++) + printf(" %s", $i) + printf("\n") + mn += 10 + }' /etc/cron.d/crontabs/root >/etc/cron.d/crontabs/root.$$ + cp /etc/cron.d/crontabs/root.$$ /etc/cron.d/crontabs/root + rm -f /etc/cron.d/crontabs/root.$$ +fi + if [ -x /usr/sbin/cron ]; then /usr/bin/rm -f /etc/cron.d/FIFO /usr/sbin/cron & |