Index: Makefile =================================================================== RCS file: /home/ncvs/src/usr.sbin/cron/cron/Makefile,v retrieving revision 1.15 diff -U2 -r1.15 Makefile --- Makefile 20 Jul 2001 06:19:40 -0000 1.15 +++ Makefile 18 Jul 2007 12:29:46 -0000 @@ -4,9 +4,10 @@ MAN= cron.8 SRCS= cron.c database.c do_command.c job.c user.c popen.c +WARNS= 2 CFLAGS+= -DLOGIN_CAP -DPADD= ${LIBCRON} ${LIBUTIL} -LDADD= ${LIBCRON} -lutil +DPADD= ${LIBCRON} ${LIBUTIL} ${LIBMAGIC} ${LIBZ} +LDADD= ${LIBCRON} -lutil -lmagic -lz .include Index: cron.8 =================================================================== RCS file: /home/ncvs/src/usr.sbin/cron/cron/cron.8,v retrieving revision 1.24 diff -U2 -r1.24 cron.8 --- cron.8 13 Feb 2005 23:45:51 -0000 1.24 +++ cron.8 18 Jul 2007 12:29:46 -0000 @@ -29,4 +29,5 @@ .Op Fl J Ar rootjitter .Op Fl s +.Op Fl m .Op Fl o .Op Fl x Ar debugflag Ns Op , Ns Ar ... @@ -105,4 +106,16 @@ .Fl j except that it will affect jobs run by the superuser only. +.It Fl m +When preparing an e-mail with a job's output (if any), try to guess the +Content-Type of the message. This uses +.Lb libmagic +-- the same mechanism, as that used by +.Nm file. +.Pp +Note, only the initial portion of the output is analyzed (typicaly +-- up to 1024 characters), which could sometimes lead to incorrect results. +For example, if the text contains its first non-ASCII character beyond +the initial portion, the charset part of the content-type may be incorrectly +set to "us-ascii". .It Fl s Enable special handling of situations when the GMT offset of the local @@ -176,5 +189,10 @@ .Sh SEE ALSO .Xr crontab 1 , -.Xr crontab 5 +.Xr crontab 5 , +.Xr file 1 , +.Xr libmagic 3 .Sh AUTHORS -.An Paul Vixie Aq paul@vix.com +.An Paul Vixie (original author) Aq paul@vix.com +.An Dmitry Morozovsky (jitter additions) +.An Sergey Babkin (time-zone changing code) Aq babkin@FreeBSD.org +.An Mikhail Teterin (Content-Type setting) Aq mi@aldan.algebra.com Index: cron.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/cron/cron/cron.c,v retrieving revision 1.15.8.1 diff -U2 -r1.15.8.1 cron.c --- cron.c 15 Jan 2006 17:50:36 -0000 1.15.8.1 +++ cron.c 18 Jul 2007 12:29:46 -0000 @@ -31,4 +31,5 @@ # include #endif +#include @@ -53,5 +54,5 @@ char **dflags; - fprintf(stderr, "usage: cron [-j jitter] [-J rootjitter] " + fprintf(stderr, "usage: cron [-j jitter] [-J rootjitter] [-m]" "[-s] [-o] [-x debugflag[,...]]\n"); fprintf(stderr, "\ndebugflags: "); @@ -433,4 +434,5 @@ } +extern magic_t Magic; static void @@ -442,6 +444,19 @@ char *endp; - while ((argch = getopt(argc, argv, "j:J:osx:")) != -1) { + while ((argch = getopt(argc, argv, "mj:J:osx:")) != -1) { switch (argch) { + case 'm': + Magic = magic_open(MAGIC_MIME|MAGIC_ERROR); + if (Magic == NULL) { + warnx("failed to allocate the magic structure"); + break; + } + if (!magic_load(Magic, NULL)) + break; + warnx("failed to load magic DB: %s", + magic_error(Magic)); + magic_close(Magic); + Magic = NULL; + break; case 'j': Jitter = strtoul(optarg, &endp, 10); Index: do_command.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/cron/cron/do_command.c,v retrieving revision 1.22.8.2 diff -U2 -r1.22.8.2 do_command.c --- do_command.c 1 Jul 2006 07:18:16 -0000 1.22.8.2 +++ do_command.c 18 Jul 2007 12:29:46 -0000 @@ -33,5 +33,8 @@ # include #endif +#include +#include +magic_t Magic = NULL; /* Try to set Content-Type in generated e-mail? */ static void child_process __P((entry *, user *)), @@ -394,5 +397,6 @@ /*local*/{ register FILE *in = fdopen(stdout_pipe[READ_PIPE], "r"); - register int ch; + char buf[BUFSIZ]; + size_t bufsize; if (in == NULL) { @@ -401,13 +405,19 @@ } - ch = getc(in); - if (ch != EOF) { + /* + * Read a little bit of the job's output -- enough to + * determine the * Content-Type of it... + */ + bufsize = fread(buf, sizeof(char), + sizeof(buf)/sizeof(char), in); + + if (bufsize > 0) { register FILE *mail; - register int bytes = 1; + off_t bytes = 0; int status = 0; Debug(DPROC|DEXT, - ("[%d] got data (%x:%c) from grandchild\n", - getpid(), ch, ch)) + ("[%d] got data (%x:%c) from grandchild, %d chars\n", + getpid(), buf[0], buf[0], (int)bufsize)) /* get name of recipient. this is MAILTO if set to a @@ -437,4 +447,5 @@ auto char mailcmd[MAX_COMMAND]; auto char hostname[MAXHOSTNAMELEN]; + const char *mimetype; (void) gethostname(hostname, MAXHOSTNAMELEN); @@ -445,6 +456,25 @@ (void) _exit(ERROR_EXIT); } + fprintf(mail, "From: %s (Cron Daemon)\n", usernm); fprintf(mail, "To: %s\n", mailto); + + if (Magic) { + mimetype = magic_buffer(Magic, + buf, bufsize*sizeof(char)); + if (mimetype == NULL) { + fprintf(mail, + "X-Cron-MagicError: %s\n", + magic_error(Magic)); + } else { + fprintf(mail, + "Mime-Version: 1.0\n" + "Content-Type: %s\n" + "Content-Transfer-" + "Encoding: 8bit\n", + mimetype); + } + } + fprintf(mail, "Subject: Cron <%s@%s> %s\n", usernm, first_word(hostname, "."), @@ -458,8 +488,4 @@ *env); fprintf(mail, "\n"); - - /* this was the first char from the pipe - */ - putc(ch, mail); } @@ -468,10 +494,13 @@ * mail pipe if we ARE mailing. */ - - while (EOF != (ch = getc(in))) { - bytes++; - if (mailto) - putc(ch, mail); - } + do { + if (mailto) { + bytes += sizeof(char) * + fwrite(buf, sizeof(char), + bufsize, mail); + } + bufsize = fread(buf, sizeof(char), + sizeof(buf)/sizeof(char), in); + } while (bufsize != 0); /* only close pipe if we opened it -- i.e., we're @@ -496,9 +525,7 @@ */ if (mailto && status) { - char buf[MAX_TEMPSTR]; - snprintf(buf, sizeof(buf), - "mailed %d byte%s of output but got status 0x%04x\n", - bytes, (bytes==1)?"":"s", + "mailed %jd byte%s of output but got status 0x%04x\n", + (intmax_t)bytes, (bytes==1)?"":"s", status); log_it(usernm, getpid(), "MAIL", buf);