示例#1
0
文件: crond.c 项目: K0T0LI/busybox
static int ChangeUser(const char *user)
{
	struct passwd *pas;
	const char *err_msg;

	/*
	 * Obtain password entry and change privileges
	 */
	pas = getpwnam(user);
	if (pas == 0) {
		crondlog("\011failed to get uid for %s", user);
		return (-1);
	}
	setenv("USER", pas->pw_name, 1);
	setenv("HOME", pas->pw_dir, 1);
	setenv("SHELL", DEFAULT_SHELL, 1);

	/*
	 * Change running state to the user in question
	 */
	err_msg = change_identity_e2str(pas);
	if (err_msg) {
		crondlog("\011%s for user %s", err_msg, user);
		return (-1);
	}
	if (chdir(pas->pw_dir) < 0) {
		crondlog("\011chdir failed: %s: %m", pas->pw_dir);
		if (chdir(TMPDIR) < 0) {
			crondlog("\011chdir failed: %s: %m", TMPDIR);
			return (-1);
		}
	}
	return (pas->pw_uid);
}
示例#2
0
static void RunJob(const char *user, CronLine *line)
{
	struct passwd *pas;
	pid_t pid;

	/* prepare things before vfork */
	pas = getpwnam(user);
	if (!pas) {
		crondlog(LVL9 "can't get uid for %s", user);
		goto err;
	}
	SetEnv(pas);

	/* fork as the user in question and run program */
	pid = vfork();
	if (pid == 0) {
		/* CHILD */
		/* change running state to the user in question */
		ChangeUser(pas);
		if (DebugOpt) {
			crondlog(LVL5 "child running %s", DEFAULT_SHELL);
		}
		execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
		crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user,
				 DEFAULT_SHELL, "-c", line->cl_Shell);
		_exit(EXIT_SUCCESS);
	}
	if (pid < 0) {
		/* FORK FAILED */
		crondlog(ERR20 "can't vfork");
 err:
		pid = 0;
	}
	line->cl_Pid = pid;
}
示例#3
0
文件: crond.c 项目: K0T0LI/busybox
static void RunJob(const char *user, CronLine * line)
{
	/* Fork as the user in question and run program */
	pid_t pid = fork();

	if (pid == 0) {
		/* CHILD */

		/* Change running state to the user in question */

		if (ChangeUser(user) < 0) {
			exit(0);
		}
#ifdef FEATURE_DEBUG_OPT
		if (DebugOpt) {
			crondlog("\005Child Running %s\n", DEFAULT_SHELL);
		}
#endif

		execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
		crondlog("\024unable to exec, user %s cmd %s -c %s\n", user,
				 DEFAULT_SHELL, line->cl_Shell);
		exit(0);
	} else if (pid < 0) {
		/* FORK FAILED */
		crondlog("\024couldn't fork, user %s\n", user);
		pid = 0;
	}
	line->cl_Pid = pid;
}
示例#4
0
文件: crond.c 项目: K0T0LI/busybox
static void
ForkJob(const char *user, CronLine * line, int mailFd,
		const char *prog, const char *cmd, const char *arg, const char *mailf)
{
	/* Fork as the user in question and run program */
	pid_t pid = fork();

	line->cl_Pid = pid;
	if (pid == 0) {
		/* CHILD */

		/* Change running state to the user in question */

		if (ChangeUser(user) < 0) {
			exit(0);
		}
#ifdef FEATURE_DEBUG_OPT
		if (DebugOpt) {
			crondlog("\005Child Running %s\n", prog);
		}
#endif

		if (mailFd >= 0) {
			dup2(mailFd, mailf != NULL);
			dup2((mailf ? mailFd : 1), 2);
			close(mailFd);
		}
		execl(prog, prog, cmd, arg, NULL);
		crondlog("\024unable to exec, user %s cmd %s %s %s\n", user, prog, cmd, arg);
		if (mailf) {
			fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
		}
		exit(0);
	} else if (pid < 0) {
		/* FORK FAILED */
		crondlog("\024couldn't fork, user %s\n", user);
		line->cl_Pid = 0;
		if (mailf) {
			remove(mailf);
		}
	} else if (mailf) {
		/* PARENT, FORK SUCCESS
		 * rename mail-file based on pid of process
		 */
		char mailFile2[128];

		snprintf(mailFile2, sizeof(mailFile2), TMPDIR "/cron.%s.%d", user, pid);
		rename(mailf, mailFile2);
	}
	/*
	 * Close the mail file descriptor.. we can't just leave it open in
	 * a structure, closing it later, because we might run out of descriptors
	 */

	if (mailFd >= 0) {
		close(mailFd);
	}
}
示例#5
0
static void ChangeUser(struct passwd *pas)
{
	/* careful: we're after vfork! */
	change_identity(pas); /* - initgroups, setgid, setuid */
	if (chdir(pas->pw_dir) < 0) {
		crondlog(LVL9 "can't chdir(%s)", pas->pw_dir);
		if (chdir(TMPDIR) < 0) {
			crondlog(DIE9 "can't chdir(%s)", TMPDIR); /* exits */
		}
	}
}
示例#6
0
文件: crond.c 项目: K0T0LI/busybox
static int TestJobs(time_t t1, time_t t2)
{
	short nJobs = 0;
	time_t t;

	/* Find jobs > t1 and <= t2 */

	for (t = t1 - t1 % 60; t <= t2; t += 60) {
		if (t > t1) {
			struct tm *tp = localtime(&t);
			CronFile *file;
			CronLine *line;

			for (file = FileBase; file; file = file->cf_Next) {
#ifdef FEATURE_DEBUG_OPT
				if (DebugOpt)
					crondlog("\005FILE %s:\n", file->cf_User);
#endif
				if (file->cf_Deleted)
					continue;
				for (line = file->cf_LineBase; line; line = line->cl_Next) {
#ifdef FEATURE_DEBUG_OPT
					if (DebugOpt)
						crondlog("\005    LINE %s\n", line->cl_Shell);
#endif
					if (line->cl_Mins[tp->tm_min] && line->cl_Hrs[tp->tm_hour] &&
						(line->cl_Days[tp->tm_mday] || line->cl_Dow[tp->tm_wday])
						&& line->cl_Mons[tp->tm_mon]) {
#ifdef FEATURE_DEBUG_OPT
						if (DebugOpt) {
							crondlog("\005    JobToDo: %d %s\n",
								line->cl_Pid, line->cl_Shell);
						}
#endif
						if (line->cl_Pid > 0) {
							crondlog("\010    process already running: %s %s\n",
								file->cf_User, line->cl_Shell);
						} else if (line->cl_Pid == 0) {
							line->cl_Pid = -1;
							file->cf_Ready = 1;
							++nJobs;
						}
					}
				}
			}
		}
	}
	return (nJobs);
}
示例#7
0
文件: crond.c 项目: K0T0LI/busybox
static void SynchronizeDir(void)
{
	/* Attempt to delete the database. */

	for (;;) {
		CronFile *file;

		for (file = FileBase; file && file->cf_Deleted; file = file->cf_Next);
		if (file == NULL) {
			break;
		}
		DeleteFile(file->cf_User);
	}

	/*
	 * Remove cron update file
	 *
	 * Re-chdir, in case directory was renamed & deleted, or otherwise
	 * screwed up.
	 *
	 * scan directory and add associated users
	 */

	remove(CRONUPDATE);
	if (chdir(CDir) < 0) {
		crondlog("\311unable to find %s\n", CDir);
	}
	{
		DIR *dir = opendir(".");
		struct dirent *den;

		if (dir) {
			while ((den = readdir(dir))) {
				if (strchr(den->d_name, '.') != NULL) {
					continue;
				}
				if (getpwnam(den->d_name)) {
					SynchronizeFile(den->d_name);
				} else {
					crondlog("\007ignoring %s\n", den->d_name);
				}
			}
			closedir(dir);
		} else {
			crondlog("\311Unable to open current dir!\n");
		}
	}
}
示例#8
0
static void RunJob(const char *user, CronLine *line)
{
	char mailFile[128];
	int mailFd = -1;

	line->cl_Pid = 0;
	line->cl_MailFlag = 0;

	if (line->cl_MailTo) {
		/* open mail file - owner root so nobody can screw with it. */
		snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, getpid());
		mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);

		if (mailFd >= 0) {
			line->cl_MailFlag = 1;
			fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user,
				line->cl_Shell);
			line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR);
		} else {
			crondlog(ERR20 "cannot create mail file %s for user %s, "
					"discarding output", mailFile, user);
		}
	}

	ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);
}
示例#9
0
static void RunJobs(void)
{
	CronFile *file;
	CronLine *line;

	for (file = FileBase; file; file = file->cf_Next) {
		if (!file->cf_Ready)
			continue;

		file->cf_Ready = 0;
		for (line = file->cf_LineBase; line; line = line->cl_Next) {
			if (line->cl_Pid >= 0)
				continue;

			RunJob(file->cf_User, line);
			crondlog(LVL8 "USER %s pid %3d cmd %s",
				file->cf_User, (int)line->cl_Pid, line->cl_Shell);
			if (line->cl_Pid < 0) {
				file->cf_Ready = 1;
			} else if (line->cl_Pid > 0) {
				file->cf_Running = 1;
			}
		}
	}
}
示例#10
0
static void log8(const char *msg, ...)
{
	va_list va;
	va_start(va, msg);
	crondlog(8, msg, va);
	va_end(va);
}
示例#11
0
文件: crond.c 项目: K0T0LI/busybox
static void RunJobs(void)
{
	CronFile *file;
	CronLine *line;

	for (file = FileBase; file; file = file->cf_Next) {
		if (file->cf_Ready) {
			file->cf_Ready = 0;

			for (line = file->cf_LineBase; line; line = line->cl_Next) {
				if (line->cl_Pid < 0) {

					RunJob(file->cf_User, line);

					crondlog("\010USER %s pid %3d cmd %s\n",
						file->cf_User, line->cl_Pid, line->cl_Shell);
					if (line->cl_Pid < 0) {
						file->cf_Ready = 1;
					}
					else if (line->cl_Pid > 0) {
						file->cf_Running = 1;
					}
				}
			}
		}
	}
}
示例#12
0
/*
 * TestJobs()
 *
 * determine which jobs need to be run.  Under normal conditions, the
 * period is about a minute (one scan).  Worst case it will be one
 * hour (60 scans).
 */
static int TestJobs(time_t t1, time_t t2)
{
	int nJobs = 0;
	time_t t;

	/* Find jobs > t1 and <= t2 */

	for (t = t1 - t1 % 60; t <= t2; t += 60) {
		struct tm *tp;
		CronFile *file;
		CronLine *line;

		if (t <= t1)
			continue;

		tp = localtime(&t);
		for (file = FileBase; file; file = file->cf_Next) {
			if (DebugOpt)
				crondlog(LVL5 "file %s:", file->cf_User);
			if (file->cf_Deleted)
				continue;
			for (line = file->cf_LineBase; line; line = line->cl_Next) {
				if (DebugOpt)
					crondlog(LVL5 " line %s", line->cl_Shell);
				if (line->cl_Mins[tp->tm_min] && line->cl_Hrs[tp->tm_hour]
				 && (line->cl_Days[tp->tm_mday] || line->cl_Dow[tp->tm_wday])
				 && line->cl_Mons[tp->tm_mon]
				) {
					if (DebugOpt) {
						crondlog(LVL5 " job: %d %s",
							(int)line->cl_Pid, line->cl_Shell);
					}
					if (line->cl_Pid > 0) {
						crondlog(LVL8 "user %s: process already running: %s",
							file->cf_User, line->cl_Shell);
					} else if (line->cl_Pid == 0) {
						line->cl_Pid = -1;
						file->cf_Ready = 1;
						++nJobs;
					}
				}
			}
		}
	}
	return nJobs;
}
示例#13
0
static void SynchronizeDir(void)
{
	CronFile *file;
	/* Attempt to delete the database. */
 again:
	for (file = FileBase; file; file = file->cf_Next) {
		if (!file->cf_Deleted) {
			DeleteFile(file->cf_User);
			goto again;
		}
	}

	/*
	 * Remove cron update file
	 *
	 * Re-chdir, in case directory was renamed & deleted, or otherwise
	 * screwed up.
	 *
	 * scan directory and add associated users
	 */
	unlink(CRONUPDATE);
	if (chdir(CDir) < 0) {
		crondlog(DIE9 "can't chdir(%s)", CDir);
	}
	{
		DIR *dir = opendir(".");
		struct dirent *den;

		if (!dir)
			crondlog(DIE9 "can't chdir(%s)", "."); /* exits */
		while ((den = readdir(dir)) != NULL) {
			if (strchr(den->d_name, '.') != NULL) {
				continue;
			}
			if (getpwnam(den->d_name)) {
				SynchronizeFile(den->d_name);
			} else {
				crondlog(LVL7 "ignoring %s", den->d_name);
			}
		}
		closedir(dir);
	}
}
示例#14
0
文件: crond.c 项目: K0T0LI/busybox
static void RunJob(const char *user, CronLine * line)
{
	char mailFile[128];
	int mailFd;

	line->cl_Pid = 0;
	line->cl_MailFlag = 0;

	/* open mail file - owner root so nobody can screw with it. */

	snprintf(mailFile, sizeof(mailFile), TMPDIR "/cron.%s.%d", user, getpid());
	mailFd = open(mailFile, O_CREAT | O_TRUNC | O_WRONLY | O_EXCL | O_APPEND, 0600);

	if (mailFd >= 0) {
		line->cl_MailFlag = 1;
		fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user,
			line->cl_Shell);
		line->cl_MailPos = lseek(mailFd, 0, 1);
	} else {
		crondlog("\024unable to create mail file user %s file %s, output to /dev/null\n", user, mailFile);
	}

	ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);
}
示例#15
0
int crond_main(int argc ATTRIBUTE_UNUSED, char **argv)
{
	unsigned opt;

	INIT_G();

	/* "-b after -f is ignored", and so on for every pair a-b */
	opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l")
			":l+:d+"; /* -l and -d have numeric param */
	opt = getopt32(argv, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"),
			&LogLevel, &LogFile, &CDir
			USE_DEBUG_CROND_OPTION(,&LogLevel));
	/* both -d N and -l N set the same variable: LogLevel */

	if (!(opt & OPT_f)) {
		/* close stdin, stdout, stderr.
		 * close unused descriptors - don't need them. */
		bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
	}

	if (!DebugOpt && LogFile == NULL) {
		/* logging to syslog */
		openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
		logmode = LOGMODE_SYSLOG;
	}

	xchdir(CDir);
	//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
	setenv("SHELL", DEFAULT_SHELL, 1); /* once, for all future children */
	crondlog(LVL9 "crond (busybox "BB_VER") started, log level %d", LogLevel);
	SynchronizeDir();

	/* main loop - synchronize to 1 second after the minute, minimum sleep
	 * of 1 second. */
	{
		time_t t1 = time(NULL);
		time_t t2;
		long dt;
		int rescan = 60;
		int sleep_time = 60;

		write_pidfile("/var/run/crond.pid");
		for (;;) {
			sleep((sleep_time + 1) - (time(NULL) % sleep_time));

			t2 = time(NULL);
			dt = (long)t2 - (long)t1;

			/*
			 * The file 'cron.update' is checked to determine new cron
			 * jobs.  The directory is rescanned once an hour to deal
			 * with any screwups.
			 *
			 * check for disparity.  Disparities over an hour either way
			 * result in resynchronization.  A reverse-indexed disparity
			 * less then an hour causes us to effectively sleep until we
			 * match the original time (i.e. no re-execution of jobs that
			 * have just been run).  A forward-indexed disparity less then
			 * an hour causes intermediate jobs to be run, but only once
			 * in the worst case.
			 *
			 * when running jobs, the inequality used is greater but not
			 * equal to t1, and less then or equal to t2.
			 */
			if (--rescan == 0) {
				rescan = 60;
				SynchronizeDir();
			}
			CheckUpdates();
			if (DebugOpt)
				crondlog(LVL5 "wakeup dt=%ld", dt);
			if (dt < -60 * 60 || dt > 60 * 60) {
				crondlog(WARN9 "time disparity of %d minutes detected", dt / 60);
			} else if (dt > 0) {
				TestJobs(t1, t2);
				RunJobs();
				sleep(5);
				if (CheckJobs() > 0) {
					sleep_time = 10;
				} else {
					sleep_time = 60;
				}
			}
			t1 = t2;
		}
	}
	return 0; /* not reached */
}
示例#16
0
文件: eooqd.c 项目: dkg/ripe-atlas-fw
int eooqd_main(int argc, char *argv[])
{
	int r;
	char *pid_file_name, *instance_id_str;
	char *check;
	struct event *checkQueueEvent, *rePostEvent;
	struct timeval tv;
	struct rlimit limit;

	atlas_id= NULL;
	instance_id_str= NULL;
	pid_file_name= NULL;
	queue_id= "";

	(void)getopt32(argv, "A:i:P:q:", &atlas_id, &instance_id_str,
		&pid_file_name, &queue_id);

	if (argc != optind+1)
	{
		bb_show_usage();
		return 1;
	}

	instance_id= 0;
	if (instance_id_str)
	{
		instance_id= strtoul(instance_id_str, &check, 0);
		if (check[0] != '\0')
		{
			report("unable to parse instance id '%s'",
				instance_id_str);
			return 1;
		}
	}

	if(pid_file_name)
	{
		write_pidfile(pid_file_name);
	}

	state = xzalloc(sizeof(*state));

	state->atlas_id= atlas_id;
	state->queue_file= argv[optind];

	state->max_busy= 10;

	state->slots= xzalloc(sizeof(*state->slots) * state->max_busy);

	if (strlen(state->queue_file) + strlen(SUFFIX) + 1 >
		sizeof(state->curr_qfile))
	{
		report("filename too long ('%s')", state->queue_file);
		return 1;
	}

	strlcpy(state->curr_qfile, state->queue_file,
		sizeof(state->curr_qfile));
	strlcat(state->curr_qfile, SUFFIX, sizeof(state->curr_qfile));

	signal(SIGQUIT, SIG_DFL);
	limit.rlim_cur= RLIM_INFINITY;
	limit.rlim_max= RLIM_INFINITY;
	setrlimit(RLIMIT_CORE, &limit);

	/* Create libevent event base */
	EventBase= event_base_new();
	if (!EventBase)
	{
		crondlog(DIE9 "event_base_new failed"); /* exits */
	}
	DnsBase= evdns_base_new(EventBase, 1 /*initialize*/);
	if (!DnsBase)
	{
		event_base_free(EventBase);
		crondlog(DIE9 "evdns_base_new failed"); /* exits */
	}

	checkQueueEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		checkQueue, NULL);
	if (!checkQueueEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 1;
	tv.tv_usec= 0;
	event_add(checkQueueEvent, &tv);

	rePostEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		re_post, NULL);
	if (!rePostEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 60;
	tv.tv_usec= 0;
	event_add(rePostEvent, &tv);

	r= event_base_loop(EventBase, 0);
	if (r != 0)
		crondlog(LVL9 "event_base_loop failed");
	return 0;
}
示例#17
0
static char *ParseField(char *user, char *ary, int modvalue, int off,
				const char *names, char *ptr)
/* 'names' is a pointer to a set of 3-char abbreviations */
{
	char *base = ptr;
	int n1 = -1;
	int n2 = -1;

	if (base == NULL) {
		return NULL;
	}

	while (!isspace(*ptr)) {
		int skip = 0;

		/* Handle numeric digit or symbol or '*' */
		if (*ptr == '*') {
			n1 = 0;		/* everything will be filled */
			n2 = modvalue - 1;
			skip = 1;
			++ptr;
		} else if (isdigit(*ptr)) {
			if (n1 < 0) {
				n1 = strtol(ptr, &ptr, 10) + off;
			} else {
				n2 = strtol(ptr, &ptr, 10) + off;
			}
			skip = 1;
		} else if (names) {
			int i;

			for (i = 0; names[i]; i += 3) {
				/* was using strncmp before... */
				if (strncasecmp(ptr, &names[i], 3) == 0) {
					ptr += 3;
					if (n1 < 0) {
						n1 = i / 3;
					} else {
						n2 = i / 3;
					}
					skip = 1;
					break;
				}
			}
		}

		/* handle optional range '-' */
		if (skip == 0) {
			crondlog(WARN9 "user %s: parse error at %s", user, base);
			return NULL;
		}
		if (*ptr == '-' && n2 < 0) {
			++ptr;
			continue;
		}

		/*
		 * collapse single-value ranges, handle skipmark, and fill
		 * in the character array appropriately.
		 */
		if (n2 < 0) {
			n2 = n1;
		}
		if (*ptr == '/') {
			skip = strtol(ptr + 1, &ptr, 10);
		}

		/*
		 * fill array, using a failsafe is the easiest way to prevent
		 * an endless loop
		 */
		{
			int s0 = 1;
			int failsafe = 1024;

			--n1;
			do {
				n1 = (n1 + 1) % modvalue;

				if (--s0 == 0) {
					ary[n1 % modvalue] = 1;
					s0 = skip;
				}
				if (--failsafe == 0) {
					crondlog(WARN9 "user %s: parse error at %s", user, base);
					return NULL;
				}
			} while (n1 != n2);

		}
		if (*ptr != ',') {
			break;
		}
		++ptr;
		n1 = -1;
		n2 = -1;
	}

	if (!isspace(*ptr)) {
		crondlog(WARN9 "user %s: parse error at %s", user, base);
		return NULL;
	}

	if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */
		/* can't use crondlog, it inserts '\n' */
		int i;
		for (i = 0; i < modvalue; ++i)
			fprintf(stderr, "%d", (unsigned char)ary[i]);
		fputc('\n', stderr);
	}
	return skip_whitespace(ptr);
}
示例#18
0
static void SynchronizeFile(const char *fileName)
{
	FILE *fi;
	struct stat sbuf;
	int maxEntries;
	int maxLines;
	char buf[1024];
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
	char *mailTo = NULL;
#endif

	if (!fileName)
		return;

	DeleteFile(fileName);
	fi = fopen(fileName, "r");
	if (!fi)
		return;

	maxEntries = MAXLINES;
	if (strcmp(fileName, "root") == 0) {
		maxEntries = 65535;
	}
	maxLines = maxEntries * 10;

	if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) {
		CronFile *file = xzalloc(sizeof(CronFile));
		CronLine **pline;

		file->cf_User = xstrdup(fileName);
		pline = &file->cf_LineBase;

		while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) {
			CronLine *line;
			char *ptr;

			trim(buf);
			if (buf[0] == '\0' || buf[0] == '#') {
				continue;
			}
			if (--maxEntries == 0) {
				break;
			}
			if (DebugOpt) {
				crondlog(LVL5 "user:%s entry:%s", fileName, buf);
			}
			/* check if line is setting MAILTO= */
			if (0 == strncmp("MAILTO=", buf, 7)) {
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
				free(mailTo);
				mailTo = (buf[7]) ? xstrdup(buf+7) : NULL;
#endif /* otherwise just ignore such lines */
				continue;
			}
			*pline = line = xzalloc(sizeof(CronLine));
			/* parse date ranges */
			ptr = ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, buf);
			ptr = ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, ptr);
			ptr = ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, ptr);
			ptr = ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, ptr);
			ptr = ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, ptr);
			/* check failure */
			if (ptr == NULL) {
				free(line);
				continue;
			}
			/*
			 * fix days and dow - if one is not "*" and the other
			 * is "*", the other is set to 0, and vise-versa
			 */
			FixDayDow(line);
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
			/* copy mailto (can be NULL) */
			line->cl_MailTo = xstrdup(mailTo);
#endif
			/* copy command */
			line->cl_Shell = xstrdup(ptr);
			if (DebugOpt) {
				crondlog(LVL5 " command:%s", ptr);
			}
			pline = &line->cl_Next;
		}
		*pline = NULL;

		file->cf_Next = FileBase;
		FileBase = file;

		if (maxLines == 0 || maxEntries == 0) {
			crondlog(WARN9 "user %s: too many lines", fileName);
		}
	}
	fclose(fi);
}
示例#19
0
文件: crond.c 项目: K0T0LI/busybox
static void SynchronizeFile(const char *fileName)
{
	int maxEntries = MAXLINES;
	int maxLines;
	char buf[1024];

	if (strcmp(fileName, "root") == 0) {
		maxEntries = 65535;
	}
	maxLines = maxEntries * 10;

	if (fileName) {
		FILE *fi;

		DeleteFile(fileName);

		fi = fopen(fileName, "r");
		if (fi != NULL) {
			struct stat sbuf;

			if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) {
				CronFile *file = calloc(1, sizeof(CronFile));
				CronLine **pline;

				file->cf_User = strdup(fileName);
				pline = &file->cf_LineBase;

				while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) {
					CronLine line;
					char *ptr;

					trim(buf);
					if (buf[0] == 0 || buf[0] == '#') {
						continue;
					}
					if (--maxEntries == 0) {
						break;
					}
					memset(&line, 0, sizeof(line));

#ifdef FEATURE_DEBUG_OPT
					if (DebugOpt) {
						crondlog("\111User %s Entry %s\n", fileName, buf);
					}
#endif

					/* parse date ranges */
					ptr = ParseField(file->cf_User, line.cl_Mins, 60, 0, NULL, buf);
					ptr = ParseField(file->cf_User, line.cl_Hrs, 24, 0, NULL, ptr);
					ptr = ParseField(file->cf_User, line.cl_Days, 32, 0, NULL, ptr);
					ptr = ParseField(file->cf_User, line.cl_Mons, 12, -1, MonAry, ptr);
					ptr = ParseField(file->cf_User, line.cl_Dow, 7, 0, DowAry, ptr);

					/* check failure */
					if (ptr == NULL) {
						continue;
					}

					/*
					 * fix days and dow - if one is not * and the other
					 * is *, the other is set to 0, and vise-versa
					 */

					FixDayDow(&line);

					*pline = calloc(1, sizeof(CronLine));
					**pline = line;

					/* copy command */
					(*pline)->cl_Shell = strdup(ptr);

#ifdef FEATURE_DEBUG_OPT
					if (DebugOpt) {
						crondlog("\111    Command %s\n", ptr);
					}
#endif

					pline = &((*pline)->cl_Next);
				}
				*pline = NULL;

				file->cf_Next = FileBase;
				FileBase = file;

				if (maxLines == 0 || maxEntries == 0) {
					crondlog("\111Maximum number of lines reached for user %s\n", fileName);
				}
			}
			fclose(fi);
		}
	}
}
示例#20
0
文件: crond.c 项目: K0T0LI/busybox
static char *ParseField(char *user, char *ary, int modvalue, int off,
						const char *const *names, char *ptr)
{
	char *base = ptr;
	int n1 = -1;
	int n2 = -1;

	if (base == NULL) {
		return (NULL);
	}

	while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') {
		int skip = 0;

		/* Handle numeric digit or symbol or '*' */

		if (*ptr == '*') {
			n1 = 0;		/* everything will be filled */
			n2 = modvalue - 1;
			skip = 1;
			++ptr;
		} else if (*ptr >= '0' && *ptr <= '9') {
			if (n1 < 0) {
				n1 = strtol(ptr, &ptr, 10) + off;
			} else {
				n2 = strtol(ptr, &ptr, 10) + off;
			}
			skip = 1;
		} else if (names) {
			int i;

			for (i = 0; names[i]; ++i) {
				if (strncmp(ptr, names[i], strlen(names[i])) == 0) {
					break;
				}
			}
			if (names[i]) {
				ptr += strlen(names[i]);
				if (n1 < 0) {
					n1 = i;
				} else {
					n2 = i;
				}
				skip = 1;
			}
		}

		/* handle optional range '-' */

		if (skip == 0) {
			crondlog("\111failed user %s parsing %s\n", user, base);
			return (NULL);
		}
		if (*ptr == '-' && n2 < 0) {
			++ptr;
			continue;
		}

		/*
		 * collapse single-value ranges, handle skipmark, and fill
		 * in the character array appropriately.
		 */

		if (n2 < 0) {
			n2 = n1;
		}
		if (*ptr == '/') {
			skip = strtol(ptr + 1, &ptr, 10);
		}
		/*
		 * fill array, using a failsafe is the easiest way to prevent
		 * an endless loop
		 */

		{
			int s0 = 1;
			int failsafe = 1024;

			--n1;
			do {
				n1 = (n1 + 1) % modvalue;

				if (--s0 == 0) {
					ary[n1 % modvalue] = 1;
					s0 = skip;
				}
			}
			while (n1 != n2 && --failsafe);

			if (failsafe == 0) {
				crondlog("\111failed user %s parsing %s\n", user, base);
				return (NULL);
			}
		}
		if (*ptr != ',') {
			break;
		}
		++ptr;
		n1 = -1;
		n2 = -1;
	}

	if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n') {
		crondlog("\111failed user %s parsing %s\n", user, base);
		return (NULL);
	}

	while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') {
		++ptr;
	}
#ifdef FEATURE_DEBUG_OPT
	if (DebugOpt) {
		int i;

		for (i = 0; i < modvalue; ++i) {
			crondlog("\005%d", ary[i]);
		}
		crondlog("\005\n");
	}
#endif

	return (ptr);
}
示例#21
0
文件: crond.c 项目: K0T0LI/busybox
int crond_main(int ac, char **av)
{
	unsigned long opt;
	char *lopt, *Lopt, *copt;

#ifdef FEATURE_DEBUG_OPT
	char *dopt;

	bb_opt_complementally = "f-b:b-f:S-L:L-S:d-l";
#else
	bb_opt_complementally = "f-b:b-f:S-L:L-S";
#endif

	opterr = 0;			/* disable getopt 'errors' message. */
	opt = bb_getopt_ulflags(ac, av, "l:L:fbSc:"
#ifdef FEATURE_DEBUG_OPT
							"d:"
#endif
							, &lopt, &Lopt, &copt
#ifdef FEATURE_DEBUG_OPT
							, &dopt
#endif
		);
	if (opt & 1) {
		LogLevel = atoi(lopt);
	}
	if (opt & 2) {
		if (*Lopt != 0) {
			LogFile = Lopt;
		}
	}
	if (opt & 32) {
		if (*copt != 0) {
			CDir = copt;
		}
	}
#ifdef FEATURE_DEBUG_OPT
	if (opt & 64) {
		DebugOpt = atoi(dopt);
		LogLevel = 0;
	}
#endif

	/*
	 * change directory
	 */

	if (chdir(CDir) != 0) {
		bb_perror_msg_and_die("%s", CDir);
	}
	signal(SIGHUP, SIG_IGN);	/* hmm.. but, if kill -HUP original
								 * version - his died. ;(
								 */
	/*
	 * close stdin and stdout, stderr.
	 * close unused descriptors -  don't need.
	 * optional detach from controlling terminal
	 */

	if (!(opt & 4)) {
#if defined(__uClinux__)
		/* reexec for vfork() do continue parent */
		vfork_daemon_rexec(1, 0, ac, av, "-f");
#else							/* uClinux */
		if (daemon(1, 0) < 0) {
			bb_perror_msg_and_die("daemon");
		}
#endif							/* uClinux */
	}

	(void) startlogger();	/* need if syslog mode selected */

	/*
	 * main loop - synchronize to 1 second after the minute, minimum sleep
	 *             of 1 second.
	 */

	crondlog("\011%s " VERSION " dillon, started, log level %d\n",
			 bb_applet_name, LogLevel);

	SynchronizeDir();

	{
		time_t t1 = time(NULL);
		time_t t2;
		long dt;
		short rescan = 60;
		short sleep_time = 60;

		for (;;) {
			sleep((sleep_time + 1) - (short) (time(NULL) % sleep_time));

			t2 = time(NULL);
			dt = t2 - t1;

			/*
			 * The file 'cron.update' is checked to determine new cron
			 * jobs.  The directory is rescanned once an hour to deal
			 * with any screwups.
			 *
			 * check for disparity.  Disparities over an hour either way
			 * result in resynchronization.  A reverse-indexed disparity
			 * less then an hour causes us to effectively sleep until we
			 * match the original time (i.e. no re-execution of jobs that
			 * have just been run).  A forward-indexed disparity less then
			 * an hour causes intermediate jobs to be run, but only once
			 * in the worst case.
			 *
			 * when running jobs, the inequality used is greater but not
			 * equal to t1, and less then or equal to t2.
			 */

			if (--rescan == 0) {
				rescan = 60;
				SynchronizeDir();
			}
			CheckUpdates();
#ifdef FEATURE_DEBUG_OPT
			if (DebugOpt)
				crondlog("\005Wakeup dt=%d\n", dt);
#endif
			if (dt < -60 * 60 || dt > 60 * 60) {
				t1 = t2;
				crondlog("\111time disparity of %d minutes detected\n", dt / 60);
			} else if (dt > 0) {
				TestJobs(t1, t2);
				RunJobs();
				sleep(5);
				if (CheckJobs() > 0) {
					sleep_time = 10;
				} else {
					sleep_time = 60;
				}
				t1 = t2;
			}
		}
	}
	/* not reached */
}
示例#22
0
static void
ForkJob(const char *user, CronLine *line, int mailFd,
		const char *prog, const char *cmd, const char *arg,
		const char *mail_filename)
{
	struct passwd *pas;
	pid_t pid;

	/* prepare things before vfork */
	pas = getpwnam(user);
	if (!pas) {
		crondlog(LVL9 "can't get uid for %s", user);
		goto err;
	}
	SetEnv(pas);

	pid = vfork();
	if (pid == 0) {
		/* CHILD */
		/* change running state to the user in question */
		ChangeUser(pas);
		if (DebugOpt) {
			crondlog(LVL5 "child running %s", prog);
		}
		if (mailFd >= 0) {
			xmove_fd(mailFd, mail_filename ? 1 : 0);
			dup2(1, 2);
		}
		execl(prog, prog, cmd, arg, NULL);
		crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user, prog, cmd, arg);
		if (mail_filename) {
			fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
		}
		_exit(EXIT_SUCCESS);
	}

	line->cl_Pid = pid;
	if (pid < 0) {
		/* FORK FAILED */
		crondlog(ERR20 "can't vfork");
 err:
		line->cl_Pid = 0;
		if (mail_filename) {
			unlink(mail_filename);
		}
	} else if (mail_filename) {
		/* PARENT, FORK SUCCESS
		 * rename mail-file based on pid of process
		 */
		char mailFile2[128];

		snprintf(mailFile2, sizeof(mailFile2), "%s/cron.%s.%d", TMPDIR, user, pid);
		rename(mail_filename, mailFile2); // TODO: xrename?
	}

	/*
	 * Close the mail file descriptor.. we can't just leave it open in
	 * a structure, closing it later, because we might run out of descriptors
	 */
	if (mailFd >= 0) {
		close(mailFd);
	}
}
示例#23
0
int eooqd_main(int argc, char *argv[])
{
	int r;
	size_t len;
	char *pid_file_name, *interface_name, *instance_id_str;
	char *check;
	struct event *checkQueueEvent, *rePostEvent;
	struct timeval tv;
	struct rlimit limit;
	struct stat sb;

	atlas_id= NULL;
	interface_name= NULL;
	instance_id_str= NULL;
	pid_file_name= NULL;
	queue_id= "";

	(void)getopt32(argv, "A:I:i:P:q:", &atlas_id, &interface_name, &instance_id_str,
		&pid_file_name, &queue_id);

	if (argc != optind+1)
	{
		bb_show_usage();
		return 1;
	}

	instance_id= 0;
	if (instance_id_str)
	{
		instance_id= strtoul(instance_id_str, &check, 0);
		if (check[0] != '\0')
		{
			report("unable to parse instance id '%s'",
				instance_id_str);
			return 1;
		}
	}

	if (interface_name)
	{
		len= strlen(RESOLV_CONF) + 1 +
			strlen(interface_name) + 1;
		resolv_conf= malloc(len);
		snprintf(resolv_conf, len, "%s.%s",
			RESOLV_CONF, interface_name);

		/* Check if this resolv.conf exists. If it doen't, switch
		 * to the standard one.
		 */
		if (stat(resolv_conf, &sb) == -1)
		{
			free(resolv_conf);
			resolv_conf= strdup(RESOLV_CONF);
		}
	}
	else
	{
		resolv_conf= strdup(RESOLV_CONF);
	}

	if(pid_file_name)
	{
		write_pidfile(pid_file_name);
	}

	state = xzalloc(sizeof(*state));

	state->atlas_id= atlas_id;
	state->queue_file= argv[optind];

	state->max_busy= 10;

	state->slots= xzalloc(sizeof(*state->slots) * state->max_busy);

	if (strlen(state->queue_file) + strlen(SUFFIX) + 1 >
		sizeof(state->curr_qfile))
	{
		report("filename too long ('%s')", state->queue_file);
		return 1;
	}

	strlcpy(state->curr_qfile, state->queue_file,
		sizeof(state->curr_qfile));
	strlcat(state->curr_qfile, SUFFIX, sizeof(state->curr_qfile));

	snprintf(output_filename, sizeof(output_filename),
		OOQD_OUT_PREFIX "%s/ooq.out", queue_id);

	signal(SIGQUIT, SIG_DFL);
	limit.rlim_cur= RLIM_INFINITY;
	limit.rlim_max= RLIM_INFINITY;
	setrlimit(RLIMIT_CORE, &limit);

	/* Ignore SIGPIPE, broken TCP sessions may trigger them */
	signal(SIGPIPE, SIG_IGN);

	/* Create libevent event base */
	EventBase= event_base_new();
	if (!EventBase)
	{
		crondlog(DIE9 "event_base_new failed"); /* exits */
	}
	DnsBase= evdns_base_new(EventBase, 0 /*initialize*/);
	if (!DnsBase)
	{
		event_base_free(EventBase);
		crondlog(DIE9 "evdns_base_new failed"); /* exits */
	}

	if (interface_name)
	{
		r= evdns_base_set_interface(DnsBase, interface_name);
		if (r == -1)
		{
			event_base_free(EventBase);
			crondlog(DIE9 "evdns_base_set_interface failed");
							 /* exits */
		}
	}

	r = evdns_base_resolv_conf_parse(DnsBase, DNS_OPTIONS_ALL,
		resolv_conf);
	if (r == -1)
	{
		event_base_free(EventBase);
		crondlog(DIE9 "evdns_base_resolv_conf_parse failed"); /* exits */
	}

	checkQueueEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		checkQueue, NULL);
	if (!checkQueueEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 1;
	tv.tv_usec= 0;
	event_add(checkQueueEvent, &tv);

	rePostEvent= event_new(EventBase, -1, EV_TIMEOUT|EV_PERSIST,
		re_post, NULL);
	if (!rePostEvent)
		crondlog(DIE9 "event_new failed"); /* exits */
	tv.tv_sec= 60;
	tv.tv_usec= 0;
	event_add(rePostEvent, &tv);

	r= event_base_loop(EventBase, 0);
	if (r != 0)
		crondlog(LVL9 "event_base_loop failed");
	return 0;
}