Date: Wed, 20 Sep 1995 19:37:08 +0200 From: Wolfram Schneider <wosch@cs.tu-berlin.de> To: current@freebsd.org Subject: from(1) Message-ID: <199509201737.TAA03936@caramba.cs.tu-berlin.de>
next in thread | raw e-mail | index | archive | help
Changes:
- add missing includes files
- minimal support for content-length
- allow reading input from stdin (-f -)
- Option '-c' print a count of matching lines
- Option '-F' use 'From:' instead 'From' line
- Option '-t' don't change access time
- Option '-v' Invert the sense of matching,
to select nonmatching lines.
Examples:
count mails in archive:
$ zcat hack.gz | from -c -f -
47
count non-freebsd mails in your mailbox:
$ from -cvs freebsd.org
3
mails from Berlin:
$ from -F -s berlin -f mbox
From: Thomas Graichen <graichen@omega.physik.fu-berlin.de>
From: Thomas Graichen <graichen@omega.physik.fu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
From: Wolfram Schneider <wosch@cs.tu-berlin.de>
--- /usr/src/usr.bin/from/from.c Fri May 27 14:31:22 1994
+++ from.c Wed Sep 20 17:03:44 1995
@@ -42,41 +42,90 @@
#endif /* not lint */
#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <paths.h>
+#include <string.h>
+#include <stdlib.h>
-main(argc, argv)
+#define CLEN "content-length:"
+#define FROM "From:"
+
+int f_from = 0; /* use `From:' field instead 'From' */
+int f_count = 0; /* don't print from lines, print count only */
+int f_invert = 0; /* invert searching */
+int f_atime = 0; /* modify access time */
+int counter = 0;
+
+int match __P((char *line, char *sender));
+int match2 __P((char *line, char *sender));
+void print_from __P((char *buf));
+
+
+void main(argc, argv)
int argc;
char **argv;
{
extern char *optarg;
extern int optind;
+
struct passwd *pwd;
- int ch, newline;
+ struct stat sb;
+ struct timeval tv[2];
+
+ int ch, newline, header, body;
char *file, *sender, *p;
#if MAXPATHLEN > BUFSIZ
char buf[MAXPATHLEN];
+ char buf2[MAXPATHLEN];
#else
char buf[BUFSIZ];
+ char buf2[BUFSIZ];
#endif
file = sender = NULL;
- while ((ch = getopt(argc, argv, "f:s:")) != EOF)
+
+ while ((ch = getopt(argc, argv, "?Fcf:s:tv")) != EOF)
switch((char)ch) {
+
+ /* use `From:' field instead 'From' */
+ case 'F':
+ f_from = 1;
+ break;
+
+ /* don't print from lines, print count only */
+ case 'c':
+ f_count = 1;
+ break;
+
+ /* use file as mailbox */
case 'f':
file = optarg;
break;
+
+ /* use only mails from sender */
case 's':
sender = optarg;
for (p = sender; *p; ++p)
if (isupper(*p))
*p = tolower(*p);
break;
+
+ /* don't modify access time */
+ case 't':
+ f_atime = 1;
+ break;
+
+ case 'v':
+ f_invert = 1;
+ break;
+
case '?':
default:
- fprintf(stderr, "usage: from [-f file] [-s sender] [user]\n");
+ fprintf(stderr, "usage: from [-Fctv] [-f file] [-s sender] [user]\n");
exit(1);
}
argv += optind;
@@ -90,34 +139,104 @@
}
file = pwd->pw_name;
}
- (void)sprintf(buf, "%s/%s", _PATH_MAILDIR, file);
- file = buf;
+ (void)sprintf(buf2, "%s/%s", _PATH_MAILDIR, file);
+ file = buf2;
}
- if (!freopen(file, "r", stdin)) {
+
+ /* stdin */
+ if (!strcmp(file, "-")) {
+ f_atime = 0; /* don't stat stdin */
+ }
+
+ /* redirect file to stdin */
+ else if (!freopen(file, "r", stdin)) {
fprintf(stderr, "from: can't read %s.\n", file);
exit(1);
+ }
+
+ /* save atime */
+ else if (f_atime) {
+ if (stat(file, &sb) < 0) {
+ perror("stat");
+ exit(1);
+ }
+ tv[0].tv_sec = sb.st_atime;
+ tv[0].tv_usec = sb.st_atime * 1000;
+ tv[1].tv_sec = sb.st_mtime;
+ tv[1].tv_usec = sb.st_mtime * 1000;
}
+
+ header = body = 0;
for (newline = 1; fgets(buf, sizeof(buf), stdin);) {
+
+ /*
+ * newline
+ * begin (next line) or end of header
+ */
if (*buf == '\n') {
newline = 1;
- continue;
+
+ /* skip bytes in body (content-length) */
+ if (header && body > 0) {
+ while(body--)
+ getc(stdin);
+ }
+ header = 0;
+ body = 0;
+ }
+
+ /* begin of header */
+ else if (newline && !strncmp(buf, "From ", 5)) {
+ if (!f_from)
+ if (!sender || match(buf + 5, sender))
+ print_from(buf);
+
+ header = 1;
+ newline = 0;
+ }
+
+ /* found "^content-length: <bytes>" in header */
+ else if (header &&
+ !strncasecmp(buf, CLEN, sizeof(CLEN) - 1) &&
+ isblank(*(buf + sizeof(CLEN) - 1))) {
+
+ body = atoi(buf + sizeof(CLEN));
+ }
+
+ /* From: */
+ else if (header && f_from &&
+ !strncasecmp(buf, FROM, sizeof(FROM) - 1) &&
+ isblank(*(buf + sizeof(FROM) - 1))) {
+
+ if (!sender || match2(buf + sizeof(FROM), sender))
+ print_from(buf);
+ }
+
+
+ }
+
+ /* print number (of matching or non-matching) mails */
+ if (f_count)
+ fprintf(stdout, "%d\n", counter);
+
+ /* reset access time */
+ if (f_atime) {
+ if (utimes(file, tv) < 0) {
+ perror("utimes");
+ exit(1);
}
- if (newline && !strncmp(buf, "From ", 5) &&
- (!sender || match(buf + 5, sender)))
- printf("%s", buf);
- newline = 0;
}
exit(0);
}
-match(line, sender)
+int match(line, sender)
register char *line, *sender;
{
register char ch, pch, first, *p, *t;
for (first = *sender++;;) {
if (isspace(ch = *line))
- return(0);
+ return(f_invert);
++line;
if (isupper(ch))
ch = tolower(ch);
@@ -125,7 +244,7 @@
continue;
for (p = sender, t = line;;) {
if (!(pch = *p++))
- return(1);
+ return(!f_invert);
if (isupper(ch = *t++))
ch = tolower(ch);
if (ch != pch)
@@ -133,4 +252,27 @@
}
}
/* NOTREACHED */
+}
+
+int match2(line, sender)
+ register char *line, *sender;
+{
+ register char *p, *s;
+
+ for (; *line; line++) {
+ for (p = line, s = sender; tolower(*p) == *s; p++, s++);
+
+ if (*s == NULL)
+ return(!f_invert);
+ }
+ return(f_invert);
+}
+
+void print_from(buf)
+ char *buf;
+{
+ if (f_count)
+ counter++;
+ else
+ printf("%s", buf);
}
--- /usr/src/usr.bin/from/from.1 Fri May 27 14:31:22 1994
+++ from.1 Wed Sep 20 16:52:01 1995
@@ -39,6 +39,7 @@
.Nd print names of those who have sent mail
.Sh SYNOPSIS
.Nm from
+.Op Fl Fctv
.Op Fl s Ar sender
.Op Fl f Ar file
.Op Ar user
@@ -49,6 +50,14 @@
.Pp
Options:
.Bl -tag -width Fl
+
+.It Fl F
+Use 'From:' field instead 'From'.
+
+.It Fl c
+Suppress normal output; instead print a count of
+matching lines.
+
.It Fl f Ar file
The supplied file
is examined instead of the invoker's mailbox.
@@ -61,6 +70,13 @@
Only mail from addresses containing
the
supplied string are printed.
+
+.It Fl t
+Don't change access time of mailbox.
+
+.It Fl v
+Invert the sense of matching, to select nonmatching lines.
+
.El
.Pp
If
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199509201737.TAA03936>
