int main(int ac, char **av) { int x; char *file = (char *)NULL; pid_t pid = 0; int uucpstyle = FALSE; /* indicating UUCP style locks */ int only_check = TRUE; /* don't make a lock */ Pname = ((Pname = strrchr(av[0], '/')) ? Pname + 1 : av[0]); for(x = 1; x < ac; x++) { if (av[x][0] == '-') { switch(av[x][1]) { case 'u': uucpstyle = TRUE; break; case 'd': Debug = TRUE; break; case 'p': if (strlen(av[x]) > 2) { pid = atoi(&av[x][2]); } else { if (++x >= ac) { bad_usage(); } pid = atoi(av[x]); } only_check = FALSE; /* wants one */ break; case 'f': if (strlen(av[x]) > 2) { file = &av[x][2]; } else { if (++x >= ac) { bad_usage(); } file = av[x]; } break; default: bad_usage(); } } } if (file == (char *)NULL || (!only_check && pid <= 0)) { bad_usage(); } if (only_check) { exit(cklock(file, uucpstyle) ? LOCK_GOOD : LOCK_BAD); } exit(mklock(file, pid, uucpstyle) ? LOCK_SET : LOCK_FAIL); }
/* * Open a file, locking using the lock types specified. Returns EAGAIN if lock * failed. */ int openlock(const char *path, int flags, u_int locks) { int fd, saved_errno; if (mklock(locks, path) != 0) return (-1); if ((fd = open(path, flags, 0)) == -1) goto error; if (lockfd(locks, fd) != 0) goto error; return (fd); error: saved_errno = errno; close(fd); rmlock(locks, path); errno = saved_errno; return (-1); }
/* Create a locked file. */ int createlock( const char *path, int flags, uid_t uid, gid_t gid, mode_t mode, u_int locks) { int fd, saved_errno; if (mklock(locks, path) != 0) return (-1); if ((fd = xcreate(path, flags, uid, gid, mode)) == -1) goto error; if (lockfd(locks, fd) != 0) goto error; return (fd); error: saved_errno = errno; close(fd); rmlock(locks, path); errno = saved_errno; return (-1); }
static int mklock(char *file) { int fd, try; Dir *dir; fd = openlock(file); if (fd >= 0) { /* make it a lock file if it wasn't */ dir = dirfstat(fd); if (dir == nil) error("%s vanished: %r", file); dir->mode |= DMEXCL; dir->qid.type |= QTEXCL; dirfwstat(fd, dir); free(dir); /* reopen in case it wasn't a lock file at last open */ close(fd); } for (try = 0; try < 65 && (fd = openlock(file)) < 0; try++) sleep(10*1000); return fd; } void main(int argc, char *argv[]) { Job *j; Tm tm; Time t; ulong now, last; /* in seconds */ int i, lock; debug = 0; ARGBEGIN{ case 'c': createuser(); exits(0); case 'd': debug = 1; break; default: usage(); }ARGEND if(debug){ readalljobs(); printjobs(); exits(0); } initcap(); /* do this early, before cpurc removes it */ switch(fork()){ case -1: fatal("can't fork: %r"); case 0: break; default: exits(0); } /* * it can take a few minutes before the file server notices that * we've rebooted and gives up the lock. */ lock = mklock("/cron/lock"); if (lock < 0) fatal("cron already running: %r"); argv0 = "cron"; srand(getpid()*time(0)); last = time(0); for(;;){ readalljobs(); /* * the system's notion of time may have jumped forward or * backward an arbitrary amount since the last call to time(). */ now = time(0); /* * if time has jumped backward, just note it and adapt. * if time has jumped forward more than a day, * just execute one day's jobs. */ if (now < last) { clog("time went backward"); last = now; } else if (now - last > Day) { clog("time advanced more than a day"); last = now - Day; } now = minute(now); for(last = minute(last); last <= now; last += Minute){ tm = *localtime(last); t.min = 1ULL << tm.min; t.hour = 1 << tm.hour; t.wday = 1 << tm.wday; t.mday = 1 << tm.mday; t.mon = 1 << (tm.mon + 1); for(i = 0; i < nuser; i++) for(j = users[i].jobs; j; j = j->next) if(j->time.min & t.min && j->time.hour & t.hour && j->time.wday & t.wday && j->time.mday & t.mday && j->time.mon & t.mon) rexec(&users[i], j); } seek(lock, 0, 0); write(lock, "x", 1); /* keep the lock alive */ /* * if we're not at next minute yet, sleep until a second past * (to allow for sleep intervals being approximate), * which synchronises with minute roll-over as a side-effect. */ sleepuntil(now + Minute + 1); } /* not reached */ }
/* * get next conversation sequence number * rmtname -> name of remote system * returns: * 0 -> no entery * 1 -> 0 sequence number */ int gnxseq(char *rmtname) { register FILE *fp0, *fp1; register struct tm *tp; int count = 0, ct, ret; char buf[BUFSIZ], name[NAMESIZE]; time_t clock; if (access(SQFILE, 0) != 0) return (0); { int i; for (i = 0; i < 5; i++) if ((ret = mklock(SQLOCK)) == SUCCESS) break; sleep(5); } if (ret != SUCCESS) { logent("CAN'T LOCK", SQLOCK); DEBUG(4, "can't lock %s\n", SQLOCK); return (0); } if ((fp0 = fopen(SQFILE, "r")) == NULL) return (0); if ((fp1 = fopen(SQTMP, "w")) == NULL) { fclose(fp0); return (0); } chmod(SQTMP, DFILEMODE); while (fgets(buf, BUFSIZ, fp0) != NULL) { ret = sscanf(buf, "%s%d", name, &ct); if (ret < 2) ct = 0; name[7] = '\0'; if (ct > 9998) ct = 0; if (strncmp(rmtname, name, SYSNSIZE) != SAME) { fputs(buf, fp1); continue; } /* * found name */ count = ++ct; time(&clock); tp = localtime(&clock); fprintf(fp1, "%s %d %d/%d-%d:%2.2d\n", name, ct, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); /* * write should be checked */ while (fgets(buf, BUFSIZ, fp0) != NULL) fputs(buf, fp1); } fclose(fp0); fclose(fp1); if (count == 0) { rmlock(SQLOCK); unlink(SQTMP); } return (count); }