View | Details | Raw Unified | Return to bug 210537 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile (-2 / +2 lines)
Lines 6-13 Link Here
6
6
7
CFLAGS+= -DLOGIN_CAP -DPAM
7
CFLAGS+= -DLOGIN_CAP -DPAM
8
8
9
DPADD=	${LIBCRON} ${LIBPAM} ${LIBUTIL}
9
DPADD=	${LIBCRON} ${LIBPAM} ${LIBUTIL} ${LIBMAGIC}
10
LDADD=	${LIBCRON} ${MINUSLPAM} -lutil
10
LDADD=	${LIBCRON} ${MINUSLPAM} -lutil -lmagic
11
11
12
WARNS?=	2
12
WARNS?=	2
13
13
(-)cron.8 (-2 / +20 lines)
Lines 28-33 Link Here
28
.Op Fl j Ar jitter
28
.Op Fl j Ar jitter
29
.Op Fl J Ar rootjitter
29
.Op Fl J Ar rootjitter
30
.Op Fl m Ar mailto
30
.Op Fl m Ar mailto
31
.Op Fl M
31
.Op Fl n
32
.Op Fl n
32
.Op Fl s
33
.Op Fl s
33
.Op Fl o
34
.Op Fl o
Lines 120-125 Link Here
120
The same as
121
The same as
121
.Fl j
122
.Fl j
122
except that it will affect jobs run by the superuser only.
123
except that it will affect jobs run by the superuser only.
124
.It Fl M
125
When preparing an e-mail with a job's output (if any), try to guess the
126
Content-Type of the message. This uses
127
.Lb libmagic
128
-- the same mechanism, as that used by
129
.Nm file.
130
.Pp
131
Note, only the initial portion of the output is analyzed (typicaly
132
-- up to 1024 characters), which could sometimes lead to incorrect results.
133
For example, if the text contains its first non-ASCII character beyond 
134
the initial portion, the charset part of the content-type may be incorrectly
135
set to "us-ascii".
123
.It Fl m Ar mailto
136
.It Fl m Ar mailto
124
Overrides the default recipient for
137
Overrides the default recipient for
125
.Nm
138
.Nm
Lines 165-173 Link Here
165
The second case is for the jobs that run less frequently.
178
The second case is for the jobs that run less frequently.
166
They are executed exactly once, they are not skipped nor
179
They are executed exactly once, they are not skipped nor
167
executed twice (unless cron is restarted or the user's
180
executed twice (unless cron is restarted or the user's
168
.Xr crontab 5
181
.Xr crontab 5 ,
182
.Xr file 1 ,
183
.Xr libmagic 3
169
is changed during such a time interval).
184
is changed during such a time interval).
170
If an interval disappears
185
.An Paul Vixie (original author) Aq paul@vix.com
186
.An Dmitry Morozovsky (jitter additions)
187
.An Sergey Babkin (time-zone changing code) Aq babkin@FreeBSD.org
188
.An Mikhail Teterin (Content-Type setting) Aq mi@aldan.algebra.com
171
due to the GMT offset change, such jobs are
189
due to the GMT offset change, such jobs are
172
executed at the same absolute point of time as they would be in the
190
executed at the same absolute point of time as they would be in the
173
old time zone.
191
old time zone.
(-)cron.c (-2 / +17 lines)
Lines 31-36 Link Here
31
#else
31
#else
32
# include <time.h>
32
# include <time.h>
33
#endif
33
#endif
34
#include <magic.h>
34
35
35
36
36
static	void	usage(void),
37
static	void	usage(void),
Lines 58-64 Link Here
58
    char **dflags;
59
    char **dflags;
59
#endif
60
#endif
60
61
61
	fprintf(stderr, "usage: cron [-j jitter] [-J rootjitter] "
62
	fprintf(stderr, "usage: cron [-j jitter] [-J rootjitter] [-m]"
62
			"[-m mailto] [-n] [-s] [-o] [-x debugflag[,...]]\n");
63
			"[-m mailto] [-n] [-s] [-o] [-x debugflag[,...]]\n");
63
#if DEBUGGING
64
#if DEBUGGING
64
	fprintf(stderr, "\ndebugflags: ");
65
	fprintf(stderr, "\ndebugflags: ");
Lines 504-509 Link Here
504
	log_close();
505
	log_close();
505
}
506
}
506
507
508
extern magic_t Magic;
507
509
508
static void
510
static void
509
parse_args(argc, argv)
511
parse_args(argc, argv)
Lines 513-519 Link Here
513
	int	argch;
515
	int	argch;
514
	char	*endp;
516
	char	*endp;
515
517
516
	while ((argch = getopt(argc, argv, "j:J:m:nosx:")) != -1) {
518
	while ((argch = getopt(argc, argv, "j:J:m:Mnosx:")) != -1) {
517
		switch (argch) {
519
		switch (argch) {
518
		case 'j':
520
		case 'j':
519
			Jitter = strtoul(optarg, &endp, 10);
521
			Jitter = strtoul(optarg, &endp, 10);
Lines 530-535 Link Here
530
		case 'm':
532
		case 'm':
531
			defmailto = optarg;
533
			defmailto = optarg;
532
			break;
534
			break;
535
		case 'M':
536
			Magic = magic_open(MAGIC_MIME|MAGIC_ERROR);
537
			if (Magic == NULL) {
538
				warnx("failed to allocate the magic structure");
539
				break;
540
			}
541
			if (!magic_load(Magic, NULL))
542
				break;
543
			warnx("failed to load magic DB: %s",
544
			    magic_error(Magic));
545
			magic_close(Magic);
546
			Magic = NULL;
547
			break;
533
		case 'n':
548
		case 'n':
534
			dont_daemonize = 1;
549
			dont_daemonize = 1;
535
			break;
550
			break;
(-)database.c (-6 / +6 lines)
Lines 33-39 Link Here
33
#define TMAX(a,b) ((a)>(b)?(a):(b))
33
#define TMAX(a,b) ((a)>(b)?(a):(b))
34
34
35
35
36
static	void		process_crontab(char *, char *, char *,
36
static	void		process_crontab(const char *, const char *, const char *,
37
					     struct stat *,
37
					     struct stat *,
38
					     cron_db *, cron_db *);
38
					     cron_db *, cron_db *);
39
39
Lines 222-229 Link Here
222
222
223
user *
223
user *
224
find_user(db, name)
224
find_user(db, name)
225
	cron_db	*db;
225
	const cron_db *db;
226
	char	*name;
226
	const char *name;
227
{
227
{
228
	char	*env_get();
228
	char	*env_get();
229
	user	*u;
229
	user	*u;
Lines 237-245 Link Here
237
237
238
static void
238
static void
239
process_crontab(uname, fname, tabname, statbuf, new_db, old_db)
239
process_crontab(uname, fname, tabname, statbuf, new_db, old_db)
240
	char		*uname;
240
	const char	*uname;
241
	char		*fname;
241
	const char	*fname;
242
	char		*tabname;
242
	const char	*tabname;
243
	struct stat	*statbuf;
243
	struct stat	*statbuf;
244
	cron_db		*new_db;
244
	cron_db		*new_db;
245
	cron_db		*old_db;
245
	cron_db		*old_db;
(-)do_command.c (-20 / +46 lines)
Lines 36-42 Link Here
36
# include <security/pam_appl.h>
36
# include <security/pam_appl.h>
37
# include <security/openpam.h>
37
# include <security/openpam.h>
38
#endif
38
#endif
39
#include <magic.h>
40
#include <inttypes.h>
39
41
42
magic_t	Magic = NULL; /* Try to set Content-Type in generated e-mail? */
40
43
41
static void		child_process(entry *, user *),
44
static void		child_process(entry *, user *),
42
			do_univ(user *);
45
			do_univ(user *);
Lines 442-448 Link Here
442
445
443
	/*local*/{
446
	/*local*/{
444
		register FILE	*in = fdopen(stdout_pipe[READ_PIPE], "r");
447
		register FILE	*in = fdopen(stdout_pipe[READ_PIPE], "r");
445
		register int	ch;
448
		char		buf[BUFSIZ];
449
		size_t		bufsize;
446
450
447
		if (in == NULL) {
451
		if (in == NULL) {
448
			warn("fdopen failed in child");
452
			warn("fdopen failed in child");
Lines 449-463 Link Here
449
			_exit(ERROR_EXIT);
453
			_exit(ERROR_EXIT);
450
		}
454
		}
451
455
452
		ch = getc(in);
456
		/*
453
		if (ch != EOF) {
457
		 * Read a little bit of the job's output -- enough to
458
		 * determine the * Content-Type of it...
459
		 */
460
		bufsize = fread(buf, sizeof(char),
461
		    sizeof(buf)/sizeof(char), in);
462
463
		if (bufsize > 0) {
454
			register FILE	*mail;
464
			register FILE	*mail;
455
			register int	bytes = 1;
465
			off_t		bytes = 0;
456
			int		status = 0;
466
			int		status = 0;
457
467
458
			Debug(DPROC|DEXT,
468
			Debug(DPROC|DEXT,
459
				("[%d] got data (%x:%c) from grandchild\n",
469
				("[%d] got data (%x:%c) from grandchild, %d chars\n",
460
					getpid(), ch, ch))
470
					getpid(), buf[0], buf[0], (int)bufsize))
461
471
462
			/* get name of recipient.  this is MAILTO if set to a
472
			/* get name of recipient.  this is MAILTO if set to a
463
			 * valid local username; USER otherwise.
473
			 * valid local username; USER otherwise.
Lines 483-488 Link Here
483
				register char	**env;
493
				register char	**env;
484
				auto char	mailcmd[MAX_COMMAND];
494
				auto char	mailcmd[MAX_COMMAND];
485
				auto char	hostname[MAXHOSTNAMELEN];
495
				auto char	hostname[MAXHOSTNAMELEN];
496
				const char	*mimetype;
486
497
487
				if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
498
				if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
488
					hostname[0] = '\0';
499
					hostname[0] = '\0';
Lines 496-501 Link Here
496
				fprintf(mail, "From: Cron Daemon <%s@%s>\n",
507
				fprintf(mail, "From: Cron Daemon <%s@%s>\n",
497
					usernm, hostname);
508
					usernm, hostname);
498
				fprintf(mail, "To: %s\n", mailto);
509
				fprintf(mail, "To: %s\n", mailto);
510
511
				if (Magic) {
512
					mimetype = magic_buffer(Magic,
513
					    buf, bufsize*sizeof(char));
514
					if (mimetype == NULL) {
515
						fprintf(mail,
516
						    "X-Cron-MagicError: %s\n",
517
						    magic_error(Magic));
518
					} else {
519
						fprintf(mail,
520
						    "Mime-Version: 1.0\n"
521
						    "Content-Type: %s\n"
522
						    "Content-Transfer-"
523
						    "Encoding: 8bit\n",
524
						    mimetype);
525
					}
526
				}
527
499
				fprintf(mail, "Subject: Cron <%s@%s> %s\n",
528
				fprintf(mail, "Subject: Cron <%s@%s> %s\n",
500
					usernm, first_word(hostname, "."),
529
					usernm, first_word(hostname, "."),
501
					e->cmd);
530
					e->cmd);
Lines 507-516 Link Here
507
					fprintf(mail, "X-Cron-Env: <%s>\n",
536
					fprintf(mail, "X-Cron-Env: <%s>\n",
508
						*env);
537
						*env);
509
				fprintf(mail, "\n");
538
				fprintf(mail, "\n");
510
511
				/* this was the first char from the pipe
512
				 */
513
				putc(ch, mail);
514
			}
539
			}
515
540
516
			/* we have to read the input pipe no matter whether
541
			/* we have to read the input pipe no matter whether
Lines 517-529 Link Here
517
			 * we mail or not, but obviously we only write to
542
			 * we mail or not, but obviously we only write to
518
			 * mail pipe if we ARE mailing.
543
			 * mail pipe if we ARE mailing.
519
			 */
544
			 */
545
			do {
546
				if (mailto) {
547
					bytes += sizeof(char) *
548
					    fwrite(buf, sizeof(char),
549
						bufsize, mail);
550
				}
551
				bufsize = fread(buf, sizeof(char),
552
				    sizeof(buf)/sizeof(char), in);
553
			} while (bufsize != 0);
520
554
521
			while (EOF != (ch = getc(in))) {
522
				bytes++;
523
				if (mailto)
524
					putc(ch, mail);
525
			}
526
527
			/* only close pipe if we opened it -- i.e., we're
555
			/* only close pipe if we opened it -- i.e., we're
528
			 * mailing...
556
			 * mailing...
529
			 */
557
			 */
Lines 545-555 Link Here
545
			 * what's going on.
573
			 * what's going on.
546
			 */
574
			 */
547
			if (mailto && status) {
575
			if (mailto && status) {
548
				char buf[MAX_TEMPSTR];
549
550
				snprintf(buf, sizeof(buf),
576
				snprintf(buf, sizeof(buf),
551
			"mailed %d byte%s of output but got status 0x%04x\n",
577
			"mailed %jd byte%s of output but got status 0x%04x\n",
552
					bytes, (bytes==1)?"":"s",
578
					(intmax_t)bytes, (bytes==1)?"":"s",
553
					status);
579
					status);
554
				log_it(usernm, getpid(), "MAIL", buf);
580
				log_it(usernm, getpid(), "MAIL", buf);
555
			}
581
			}
(-)popen.c (-2 / +3 lines)
Lines 56-63 Link Here
56
56
57
FILE *
57
FILE *
58
cron_popen(program, type, e)
58
cron_popen(program, type, e)
59
	char *program, *type;
59
	char		*program;
60
	entry *e;
60
	const char	*type;
61
	const entry	*e;
61
{
62
{
62
	register char *cp;
63
	register char *cp;
63
	FILE *iop;
64
	FILE *iop;
(-)user.c (-2 / +2 lines)
Lines 44-50 Link Here
44
44
45
static void
45
static void
46
log_error(msg)
46
log_error(msg)
47
	char	*msg;
47
	const char	*msg;
48
{
48
{
49
	log_it(User_name, getpid(), "PARSE", msg);
49
	log_it(User_name, getpid(), "PARSE", msg);
50
}
50
}
Lines 53-59 Link Here
53
load_user(crontab_fd, pw, name)
53
load_user(crontab_fd, pw, name)
54
	int		crontab_fd;
54
	int		crontab_fd;
55
	struct passwd	*pw;		/* NULL implies syscrontab */
55
	struct passwd	*pw;		/* NULL implies syscrontab */
56
	char		*name;
56
	const char	*name;
57
{
57
{
58
	char	envstr[MAX_ENVSTR];
58
	char	envstr[MAX_ENVSTR];
59
	FILE	*file;
59
	FILE	*file;

Return to bug 210537